Заметка
Доступ к этой странице требует авторизации. Вы можете попробовать войти в систему или изменить каталог.
Доступ к этой странице требует авторизации. Вы можете попробовать сменить директорию.
Функции Azure выполняют код приложения с помощью обработчиков, относящихся к языку. Эти обработчики, относящиеся к языку, позволяют функциям поддерживать большинство ключевых языков по умолчанию. Однако может потребоваться выполнить код на другом языке или пакете.
Пользовательские обработчики — это легковесные веб-серверы, получающие события из процесса узла Azure Functions. Пользовательские обработчики можно использовать для развертывания в Функциях Azure любого проекта кода, поддерживающего примитивы HTTP.
Пользовательские обработчики лучше всего подходят для следующих ситуаций.
- Реализуйте приложение-функцию на языке, который в настоящее время не предоставляется вне коробки, например Go или Rust.
- Реализация приложения-функции в среде выполнения, которая в настоящее время не входит в число рекомендуемых по умолчанию, например Deno.
- Разверните сервер, построенный с использованием стандартных SDK MCP, в Функциях Azure.
С помощью пользовательских обработчиков можно использовать триггеры, входные и выходные привязки посредством пакетов расширений.
Приступая к работе с пользовательскими обработчиками Функций Azure, ознакомьтесь с краткими руководствами по Go и Rust.
Обзор
На следующей схеме показана связь между узлом Функций и веб-сервером, реализованным в качестве пользовательского обработчика.
- Каждое событие формирует запрос к узлу Функций. Событие — это любой триггер, поддерживаемый Функциями Azure.
- Узел функций передает полезные данные запроса на веб-сервер. Полезные данные содержат данные триггера и входные данные привязки, а также другие метаданные для функции.
- Веб-сервер выполняет отдельную функцию и возвращает полезные данные ответа на узел Функций.
- Узел Функций передает данные из ответа в выходные привязки функции для обработки.
Приложение "Функции Azure", реализованное как пользовательский обработчик, должно настраивать файлы host.json, local.settings.json и function.json в соответствии с некоторыми соглашениями.
Развертывание локальных серверов MCP
Пользовательские обработчики также позволяют вам размещать серверы MCP, созданные с помощью официальных SDK MCP в Azure Functions. Пользовательские обработчики предоставляют простой и удобный интерфейс для размещения серверов MCP в Azure. Дополнительные сведения см. в разделе "Локальный удаленный сервер MCP" в Функциях Azure.
Примечание.
Возможность использования Azure Functions для размещения серверов MCP, которые вы создаете с помощью официальных SDK MCP, в настоящее время находится в стадии предварительного просмотра.
Структура приложений
Для реализации пользовательского обработчика приложению требуются следующие аспекты:
- Файл host.json в корне файловой системы вашего приложения
- Файл local.settings.json файловой системы вашего приложения
- Файл function.json для каждой функции (в папке, соответствующей имени функции)
- Команда, скрипт или исполняемый файл, на котором запущен веб-сервер
На следующей схеме показано, как эти файлы выглядят в файловой системе для функции с именем MyQueueFunction и исполняемым файлом пользовательского обработчика с именем handler.exe.
| /MyQueueFunction
| function.json
|
| host.json
| local.settings.json
| handler.exe
Настройка
Вы настраиваете приложение с помощью host.json и local.settings.json файлов.
host.json
host.json направляет узел Функций, куда отправлять запросы, указывая на веб-сервер, который может обрабатывать события HTTP.
Определите пользовательский обработчик, настроив файлhost.json с подробными сведениями о том, как запустить веб-сервер через customHandler раздел.
{
"version": "2.0",
"customHandler": {
"description": {
"defaultExecutablePath": "handler.exe"
}
}
}
Раздел customHandler указывает на целевой объект, как определено в defaultExecutablePath. Целевой объект выполнения может быть командой, исполняемым файлом или файлом, в котором реализуется веб-сервер.
Используйте массив arguments для передачи аргументов в исполняемый файл. Аргументы поддерживают расширение переменных среды (параметров приложения) с помощью %% нотации.
Кроме того, можно изменить рабочую папку, используемую исполняемым файлом на workingDirectory.
{
"version": "2.0",
"customHandler": {
"description": {
"defaultExecutablePath": "app/handler.exe",
"arguments": [
"--database-connection-string",
"%DATABASE_CONNECTION_STRING%"
],
"workingDirectory": "app"
}
}
}
Поддержка привязок
Стандартные триггеры, а также входные и выходные привязки доступны по ссылке на пакеты расширений в вашем файле host.json.
local.settings.json
В файле local.settings.json определяются параметры приложения, используемые при локальном выполнении приложения-функции. Поскольку он может содержать секреты, исключите local.settings.json из системы контроля версий. В Azure вместо этого используйте параметры приложения.
Для пользовательских обработчиков установите для параметра FUNCTIONS_WORKER_RUNTIME значение Custom в файле local.settings.json.
{
"IsEncrypted": false,
"Values": {
"FUNCTIONS_WORKER_RUNTIME": "Custom"
}
}
Метаданные функции
При использовании пользовательского обработчика содержимое function.json совпадает с тем, что при определении функции в любом другом контексте. Единственное требование заключается в том, что необходимо поместить function.json файлы в папку с именем функции.
В следующем файле function.jsоn настраивается функция, которая содержит триггер очереди и выходную привязку очереди. Так как файл находится в папке с именем MyQueueFunction, он определяет функцию с именем MyQueueFunction.
MyQueueFunction/function.json
{
"bindings": [
{
"name": "myQueueItem",
"type": "queueTrigger",
"direction": "in",
"queueName": "messages-incoming",
"connection": "AzureWebJobsStorage"
},
{
"name": "$return",
"type": "queue",
"direction": "out",
"queueName": "messages-outgoing",
"connection": "AzureWebJobsStorage"
}
]
}
Полезные данные запроса
Когда хост функции получает сообщение очереди, он отправляет HTTP POST-запрос в пользовательский обработчик с полезными данными в теле запроса.
В следующем коде показан пример полезной нагрузки запроса. Полезные данные включают структуру JSON с двумя элементами: Data и Metadata.
DataЭлемент содержит ключи, соответствующие именам входных данных и триггера, как определено в массиве привязок в файле function.json.
MetadataЭлемент содержит метаданные, созданные из источника событий.
{
"Data": {
"myQueueItem": "{ message: \"Message sent\" }"
},
"Metadata": {
"DequeueCount": 1,
"ExpirationTime": "2019-10-16T17:58:31+00:00",
"Id": "800ae4b3-bdd2-4c08-badd-f08e5a34b865",
"InsertionTime": "2019-10-09T17:58:31+00:00",
"NextVisibleTime": "2019-10-09T18:08:32+00:00",
"PopReceipt": "AgAAAAMAAAAAAAAAAgtnj8x+1QE=",
"sys": {
"MethodName": "QueueTrigger",
"UtcNow": "2019-10-09T17:58:32.2205399Z",
"RandGuid": "24ad4c06-24ad-4e5b-8294-3da9714877e9"
}
}
}
Полезные данные ответа
По соглашению ответы функций форматируются в пары "ключ/значение". Поддерживаются следующие ключи.
|
|
Тип данных | Замечания |
|---|---|---|
Outputs |
объект | Содержит значения ответа, определенные в виде массива bindings в файле function.json.Например, если функция настроена с выходной привязкой очереди с именем "myQueueOutput", то Outputs содержит ключ с именем myQueueOutput, который настраиваемый обработчик использует для отправки сообщений в очередь. |
Logs |
array | Сообщения, отображаемые в журналах вызовов функций. При работе в Azure сообщения отображаются в Application Insights. |
ReturnValue |
строка | Используется для предоставления ответа, когда выходные данные настраиваются как $return в файле function.json. |
В этой таблице показан пример нагрузки ответа.
{
"Outputs": {
"res": {
"body": "Message enqueued"
},
"myQueueOutput": [
"queue message 1",
"queue message 2"
]
},
"Logs": [
"Log message 1",
"Log message 2"
],
"ReturnValue": "{\"hello\":\"world\"}"
}
Примеры
Можно реализовать собственные обработчики на любом языке, поддерживающем получение HTTP-событий. В следующих примерах показано, как реализовать пользовательский обработчик с помощью языка программирования Go.
Функция с привязками
В этом примере показана функция с именем order, которая принимает запрос POST с полезной нагрузкой, представляющей заказ товара. При публикации заказа в функцию создается сообщение хранилища очередей и возвращается HTTP-ответ.
Внедрение
В папке с именем order файл function.json содержит настройки функции для триггеров HTTP.
order/function.json
{
"bindings": [
{
"type": "httpTrigger",
"direction": "in",
"name": "req",
"methods": ["post"]
},
{
"type": "http",
"direction": "out",
"name": "res"
},
{
"type": "queue",
"name": "message",
"direction": "out",
"queueName": "orders",
"connection": "AzureWebJobsStorage"
}
]
}
Эта функция определяется как функция, для триггеров HTTP, которая возвращает ответ HTTP и выводит сообщение Хранилища очередей.
Файл host.json, находящийся в корне файловой системы приложения, настраивается для запуска исполняемого файла с именем handler.exe (handler в Linux или macOS).
{
"version": "2.0",
"customHandler": {
"description": {
"defaultExecutablePath": "handler.exe"
}
},
"extensionBundle": {
"id": "Microsoft.Azure.Functions.ExtensionBundle",
"version": "[4.*, 5.0.0)"
}
}
Это HTTP-запрос, отправленный в среду выполнения Функций.
POST http://127.0.0.1:7071/api/order HTTP/1.1
Content-Type: application/json
{
"id": 1005,
"quantity": 2,
"color": "black"
}
Среда выполнения Функций отправляет следующий HTTP-запрос пользовательскому обработчику:
POST http://127.0.0.1:<FUNCTIONS_CUSTOMHANDLER_PORT>/order HTTP/1.1
Content-Type: application/json
{
"Data": {
"req": {
"Url": "http://localhost:7071/api/order",
"Method": "POST",
"Query": "{}",
"Headers": {
"Content-Type": [
"application/json"
]
},
"Params": {},
"Body": "{\"id\":1005,\"quantity\":2,\"color\":\"black\"}"
}
},
"Metadata": {
}
}
Примечание.
Некоторые части полезных данных были удалены для наглядности.
handler.exe — это скомпилированная программа пользовательского обработчика на языке Go, которая запускает веб-сервер и реагирует на запросы вызова функций от узла Функций.
package main
import (
"encoding/json"
"fmt"
"log"
"net/http"
"os"
)
type InvokeRequest struct {
Data map[string]json.RawMessage
Metadata map[string]interface{}
}
type InvokeResponse struct {
Outputs map[string]interface{}
Logs []string
ReturnValue interface{}
}
func orderHandler(w http.ResponseWriter, r *http.Request) {
var invokeRequest InvokeRequest
d := json.NewDecoder(r.Body)
d.Decode(&invokeRequest)
var reqData map[string]interface{}
json.Unmarshal(invokeRequest.Data["req"], &reqData)
outputs := make(map[string]interface{})
outputs["message"] = reqData["Body"]
resData := make(map[string]interface{})
resData["body"] = "Order enqueued"
outputs["res"] = resData
invokeResponse := InvokeResponse{outputs, nil, nil}
responseJson, _ := json.Marshal(invokeResponse)
w.Header().Set("Content-Type", "application/json")
w.Write(responseJson)
}
func main() {
customHandlerPort, exists := os.LookupEnv("FUNCTIONS_CUSTOMHANDLER_PORT")
if !exists {
customHandlerPort = "8080"
}
mux := http.NewServeMux()
mux.HandleFunc("/order", orderHandler)
fmt.Println("Go server Listening on: ", customHandlerPort)
log.Fatal(http.ListenAndServe(":"+customHandlerPort, mux))
}
В этом примере настраиваемый обработчик запускает веб-сервер для обработки событий HTTP и прослушивает запросы через FUNCTIONS_CUSTOMHANDLER_PORT.
Несмотря на то, что узел Functions получает исходный HTTP-запрос по адресу /api/order, он вызывает пользовательский обработчик, используя имя функции, которое является и именем его папки. В этом примере функция определена по пути /order. Узел отправляет HTTP-запрос пользовательского обработчика по пути /order.
При отправке POST запросов в эту функцию данные триггера и метаданные функции доступны через текст HTTP-запроса. Вы можете получить доступ к исходному тексту HTTP-запроса в Data.req.Body полезной нагрузке.
Ответ функции форматируется в пары "ключ/значение", где элемент Outputs содержит значение JSON, в котором ключи соответствуют выходным данным, определенным в файле function.json.
Это пример полезных данных, которые этот обработчик возвращает узлу Функций.
{
"Outputs": {
"message": "{\"id\":1005,\"quantity\":2,\"color\":\"black\"}",
"res": {
"body": "Order enqueued"
}
},
"Logs": null,
"ReturnValue": null
}
Если задать выходные данные message совпадающими с данными заказа, которые были получены из запроса, функция выводит эти данные заказа в настроенную очередь. Узел Функций также возвращает вызывающему ответ HTTP, настроенный в res.
Функция только HTTP
Для функций, активируемых по HTTP без дополнительных привязок или выходных данных, может потребоваться, чтобы обработчик работал непосредственно с HTTP-запросом и HTTP-ответом вместо тела запроса обработчика и тела ответа. Это поведение можно настроить в host.json с помощью enableProxyingHttpRequest параметра, который поддерживает потоковую передачу ответов.
Внимание
Основной целью функции пользовательских обработчиков является обеспечение поддержки языков и сред выполнения, для которых в данный момент отсутствует первоклассная поддержка в Функциях Azure. Хотя вы можете запускать веб-приложения с помощью пользовательских обработчиков, Azure Functions не являются стандартным обратным прокси-сервером. Некоторые компоненты HTTP-запроса, такие как определенные заголовки и маршруты, могут быть ограничены. Приложение также может столкнуться с чрезмерным холодным запуском.
Чтобы устранить эти проблемы, попробуйте запускать веб-приложения в Службе приложений Azure.
В следующем примере показан способ настройки функции для триггеров HTTP без дополнительных привязок или выходных данных. Сценарий, реализованный в этом примере, поддерживает функцию с именем hello, которая принимает GET или POST.
Внедрение
В папке с именем hello файл function.json содержит настройки функции для триггеров HTTP.
hello/function.json
{
"bindings": [
{
"type": "httpTrigger",
"authLevel": "anonymous",
"direction": "in",
"name": "req",
"methods": ["get", "post"]
},
{
"type": "http",
"direction": "out",
"name": "res"
}
]
}
Функция настроена для приема и GETPOST запросов, а значение результата предоставляется с помощью аргумента с именем res.
Файл host.json, находящийся в корне файловой системы приложения, настраивается для запуска handler.exe, и для параметра enableProxyingHttpRequest устанавливается значение true.
{
"version": "2.0",
"customHandler": {
"description": {
"defaultExecutablePath": "handler.exe"
},
"enableProxyingHttpRequest": true
}
}
Ниже приведен запрос POST к узлу функций. Затем хост функций отправляет запрос пользовательскому обработчику.
POST http://127.0.0.1:7071/api/hello HTTP/1.1
Content-Type: application/json
{
"message": "Hello World!"
}
Файл handler.go реализует веб-сервер и функцию HTTP.
package main
import (
"fmt"
"io/ioutil"
"log"
"net/http"
"os"
)
func helloHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
if r.Method == "GET" {
w.Write([]byte("hello world"))
} else {
body, _ := ioutil.ReadAll(r.Body)
w.Write(body)
}
}
func main() {
customHandlerPort, exists := os.LookupEnv("FUNCTIONS_CUSTOMHANDLER_PORT")
if !exists {
customHandlerPort = "8080"
}
mux := http.NewServeMux()
mux.HandleFunc("/api/hello", helloHandler)
fmt.Println("Go server Listening on: ", customHandlerPort)
log.Fatal(http.ListenAndServe(":"+customHandlerPort, mux))
}
В этом примере настраиваемый обработчик создает веб-сервер для обработки событий HTTP и прослушивает запросы через .FUNCTIONS_CUSTOMHANDLER_PORT
Запросы GET обрабатываются возвратом строкового значения, а запросы POST имеют доступ к тексту запроса.
Маршрут для функции заказа /api/hello имеет то же значение, что и исходный запрос.
Примечание.
FUNCTIONS_CUSTOMHANDLER_PORT не является общедоступным портом, используемым для вызова функции. Хост функций использует этот порт для вызова пользовательского обработчика.
Развертывание
Вы можете развернуть пользовательский обработчик в каждом варианте размещения Функций Azure. Если обработчику требуются зависимости операционной системы или платформы (например, языковая среда выполнения), может потребоваться использовать пользовательский контейнер.
При создании приложения-функции в Azure для пользовательских обработчиков выберите .NET Core в качестве стека.
Чтобы развернуть пользовательское приложение обработчика с помощью основных инструментов Функций Azure, выполните следующую команду.
func azure functionapp publish $functionAppName
Примечание.
Убедитесь, что все файлы, необходимые для выполнения пользовательского обработчика, находятся в папке и включены в развертывание. Если пользовательский обработчик является двоичным исполняемым файлом или имеет зависящие от платформы зависимости, убедитесь, что эти файлы соответствуют целевой платформе развертывания.
Ограничения
- Веб-сервер пользовательского обработчика должен запускаться в течение 60 секунд.
Примеры
Для примеров реализации функций на различных языках смотрите образцы в репозитории GitHub с примерами пользовательских обработчиков.
Устранение неполадок и поддержка
Просмотр журналов трассировки Java в Application Insights
Если не удается запустить процесс пользовательской обработки или возникают проблемы с взаимодействием с узлом функций, увеличьте уровень ведения журнала приложения функции, чтобы с Trace просмотреть больше диагностических сообщений от узла.
Чтобы изменить уровень ведения журнала приложения-функции по умолчанию, настройте logLevel параметр в разделе logging файла host.json.
{
"version": "2.0",
"customHandler": {
"description": {
"defaultExecutablePath": "handler.exe"
}
},
"logging": {
"logLevel": {
"default": "Trace"
}
}
}
Узел Функций выводит дополнительные сообщения журнала, включая сведения, связанные с процессом пользовательского обработчика. Используйте журналы для изучения проблем, возникающих при запуске процесса пользовательского обработчика или вызова функций в пользовательском обработчике.
В локальной среде журналы выводятся на консоль.
В Azure запросите трассировки Application Insights, чтобы просмотреть сообщения журнала. Если приложение значительно увеличивает объем журналов, в Application Insights передается только подмножество сообщений журнала. Отключите выборку, чтобы убедиться в записи всех сообщений в журнал.
Тестирование пользовательского обработчика в изоляции
Пользовательские приложения обработчика представляют собой процессы веб-сервера, поэтому может быть полезно запускать их отдельно и тестировать вызов функций, отправляя тестовые HTTP-запросы. Для отправки HTTP-запросов с полезными данными обязательно выберите средство, которое обеспечивает безопасность данных. Дополнительные сведения см. в средствах тестирования HTTP.
Эту стратегию можно использовать в конвейерах CI/CD для выполнения автоматических тестов в пользовательском обработчике.
Среда выполнения
Пользовательские обработчики запускаются в той же среде, что и типовое приложение Функций Azure. Протестируйте обработчик, чтобы убедиться, что среда содержит все зависимости, необходимые для выполнения. Для приложений, требующих дополнительных зависимостей, может потребоваться запустить их с помощью пользовательского образа контейнера, размещенного в Azure Functions Premium план.
Поддержка
Если вам нужна помощь в приложении-функции с пользовательскими обработчиками, вы можете отправить запрос по регулярным каналам поддержки. Однако из-за широкого разнообразия возможных языков, используемых для создания приложений пользовательских обработчиков, поддержка имеет свои ограничения.
Поддержка доступна, если в узле Функций имеются проблемы при запуске или взаимодействии с процессом настраиваемого обработчика. Для проблем, связанных с внутренней работой пользовательского обработчика, например проблем с выбранным языком или платформой, наша группа поддержки не может предоставить помощь в этом контексте.
Следующие шаги
Приступая к созданию приложения "Функции Azure" на языке Go или Rust, ознакомьтесь с кратким руководством по пользовательским обработчикам.