Ескертпе
Бұл бетке кіру үшін қатынас шегін айқындау қажет. Жүйеге кіруді немесе каталогтарды өзгертуді байқап көруге болады.
Бұл бетке кіру үшін қатынас шегін айқындау қажет. Каталогтарды өзгертуді байқап көруге болады.
Функции 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": "function",
"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, ознакомьтесь с кратким руководством по пользовательским обработчикам.