Not
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Azure Functions kör din appkod med hjälp av språkspecifika hanterare. Dessa språkspecifika hanterare tillåter att Functions stöder de flesta nyckelspråk som standard. Du kan dock behöva köra kod på ett annat språk eller paket.
Anpassade hanterare är lättviktiga webbservrar som tar emot händelser från Azure Functions värdprocess. Du kan använda anpassade hanterare för att distribuera alla kodprojekt som stöder HTTP-primitiver till Azure Functions.
Anpassade hanterare passar bäst för situationer där du vill:
- Implementera en funktionsapp på ett språk som för närvarande inte erbjuds direkt, till exempel Go eller Rust.
- Implementera en funktionsapp i en körning som för närvarande inte visas som standard, till exempel Deno.
- Distribuera en server som skapats med standard-MCP SDK:er till Azure Functions.
Med anpassade hanterare kan du använda utlösare och indata- och utdatabindningar via tilläggspaket.
Kom igång med anpassade Azure Functions-hanterare med snabbstarter i Go och Rust.
Översikt
Följande diagram visar relationen mellan Functions-värden och en webbserver som implementerats som en anpassad hanterare.
- Varje händelse utlöser en begäran som skickas till Functions-värden. En händelse är en utlösare som stöds av Azure Functions.
- Functions-värden utfärdar sedan en nyttolast för begäran till webbservern. Nyttolasten innehåller utlösar- och indatabindningsdata och andra metadata för funktionen.
- Webbservern kör den enskilda funktionen och returnerar en svarsnyttolast till Functions-värden.
- Functions-värden skickar data från svaret till funktionens utdatabindningar för bearbetning.
En Azure Functions-app som implementeras som en anpassad hanterare måste konfigurera host.json, local.settings.json och function.json filer enligt några konventioner.
Distribuera mcp-servrar med egen värd
Med anpassade hanterare kan du också vara värd för MCP-servrar som du skapar med hjälp av officiella MCP-SDK:er i Azure Functions. Anpassade hanterare ger en enkel och smidig upplevelse för att vara värd för dina MCP-servrar i Azure. Mer information finns i Lokalt installerad fjärr-MCP-server på Azure Functions.
Kommentar
Möjligheten att ha Azure Functions som värd för MCP-servrar som du skapar med hjälp av officiella MCP-SDK:er finns för närvarande i förhandsversion.
Programstruktur
För att implementera en anpassad hanterare behöver programmet följande aspekter:
- En host.json fil i appens rot
- En local.settings.json fil i appens rot
- En function.json fil för varje funktion (i en mapp som matchar funktionsnamnet)
- Ett kommando, ett skript eller en körbar fil som kör en webbserver
Följande diagram visar hur dessa filer ser ut i filsystemet för en funktion med namnet "MyQueueFunction" och en anpassad körbar hanterare med namnet handler.exe.
| /MyQueueFunction
| function.json
|
| host.json
| local.settings.json
| handler.exe
Konfiguration
Du konfigurerar programmet via host.json - och local.settings.json-filerna .
host.json
host.json styr Functions-värd vart förfrågningar skickas genom att peka på en webbserver som kan bearbeta HTTP-händelser.
Definiera en anpassad hanterare genom att konfigurera host.json-filen med information om hur du kör webbservern via customHandler avsnittet.
{
"version": "2.0",
"customHandler": {
"description": {
"defaultExecutablePath": "handler.exe"
}
}
}
Avsnittet customHandler pekar på ett mål som definieras av defaultExecutablePath. Körningsmålet kan vara ett kommando, ett körbart program eller en fil där webbservern är implementerad.
Använd matrisen arguments för att skicka alla argument till den körbara filen. Argument stöder expansion av miljövariabler (programinställningar) med hjälp %% av notation.
Du kan också ändra arbetskatalogen som används av den körbara filen med workingDirectory.
{
"version": "2.0",
"customHandler": {
"description": {
"defaultExecutablePath": "app/handler.exe",
"arguments": [
"--database-connection-string",
"%DATABASE_CONNECTION_STRING%"
],
"workingDirectory": "app"
}
}
}
Stöd för bindningar
Standardutlösare tillsammans med indata- och utdatabindningar är tillgängliga genom att referera till tilläggspaket i din host.json-fil .
local.settings.json
local.settings.json definierar programinställningar som används när du kör funktionsappen lokalt. Eftersom den kan innehålla hemligheter, uteslut local.settings.json från källkontrollen. I Azure använder du programinställningar i stället.
För anpassade hanterare anger du FUNCTIONS_WORKER_RUNTIME till Custom i local.settings.json.
{
"IsEncrypted": false,
"Values": {
"FUNCTIONS_WORKER_RUNTIME": "Custom"
}
}
Funktionsmetadata
När du använder en anpassad hanterare är detfunction.json innehållet samma som när du definierar en funktion i andra sammanhang. Det enda kravet är att du måste placera function.json filer i en mapp med namnet för att matcha funktionsnamnet.
Följande function.json konfigurerar en funktion som har en köutlösare och en köutdatabindning. Eftersom den finns i en mapp med namnet MyQueueFunction, definierar den en funktion med namnet 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"
}
]
}
Begär nyttolast
När Functions-värden tar emot ett kömeddelande skickar den en HTTP POST-begäran till den anpassade hanteraren med en nyttolast i begärans kropp.
Följande kod visar en nyttolast för exempelbegäran. Nyttolasten innehåller en JSON-struktur med två medlemmar: Data och Metadata.
Medlemmen Data innehåller nycklar som matchar indata- och utlösarnamn enligt definitionen i bindningsmatrisen i function.json-filen.
Medlemmen Metadata innehåller metadata som genererats från händelsekällan.
{
"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"
}
}
}
Svarsnyttolast
Enligt konvention formateras funktionssvaren som nyckel/värde-par. Nycklar som stöds är:
|
|
Datatyp | Kommentarer |
|---|---|---|
Outputs |
objekt | Innehåller svarsvärden som definierats av matrisen bindings i function.json.Om en funktion till exempel har konfigurerats med en köutdatabindning med namnet "myQueueOutput" innehåller den en Outputs nyckel med namnet myQueueOutput, som den anpassade hanteraren anger till de meddelanden som den skickar till kön. |
Logs |
matris | Meddelanden som visas i functions-anropsloggarna. När du kör i Azure visas meddelanden i Application Insights. |
ReturnValue |
sträng | Används för att ge ett svar när utdata konfigureras som $return i function.json-filen. |
Den här tabellen visar ett exempel på en svarspayload.
{
"Outputs": {
"res": {
"body": "Message enqueued"
},
"myQueueOutput": [
"queue message 1",
"queue message 2"
]
},
"Logs": [
"Log message 1",
"Log message 2"
],
"ReturnValue": "{\"hello\":\"world\"}"
}
Exempel
Du kan implementera anpassade hanterare på valfritt språk som stöder mottagning av HTTP-händelser. I följande exempel visas hur du implementerar en anpassad hanterare med hjälp av programmeringsspråket Go.
Funktion med bindningar
Det här exemplet visar en funktion med namnet order som accepterar en POST begäran med en nyttolast som representerar en produktbeställning. När du publicerar en order till funktionen skapas ett kölagringsmeddelande och ett HTTP-svar returneras.
Implementering
I en mapp med namnet order konfigurerar function.json-filen den HTTP-utlösta funktionen.
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"
}
]
}
Den här funktionen definieras som en HTTP-utlöst funktion som returnerar ett HTTP-svar och matar ut ett kölagringsmeddelande .
I appens rot är host.json-filen konfigurerad för att köra en körbar fil med namnet handler.exe (handler i Linux eller macOS).
{
"version": "2.0",
"customHandler": {
"description": {
"defaultExecutablePath": "handler.exe"
}
},
"extensionBundle": {
"id": "Microsoft.Azure.Functions.ExtensionBundle",
"version": "[4.*, 5.0.0)"
}
}
Det här är HTTP-begäran som skickas till Functions-körningen.
POST http://127.0.0.1:7071/api/order HTTP/1.1
Content-Type: application/json
{
"id": 1005,
"quantity": 2,
"color": "black"
}
Functions-körningen skickar följande HTTP-begäran till den anpassade hanteraren:
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": {
}
}
Kommentar
Vissa delar av nyttolasten har tagits bort för korthet.
handler.exe är det kompilerade go-anpassade hanteringsprogrammet som kör en webbserver och svarar på funktionsanropsbegäranden från Functions-värden.
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))
}
I det här exemplet kör den anpassade hanteraren en webbserver för att hantera HTTP-händelser och lyssnar efter begäranden via FUNCTIONS_CUSTOMHANDLER_PORT.
Även om Functions-värden tar emot den ursprungliga HTTP-begäran på /api/orderanropar den den anpassade hanteraren med hjälp av funktionsnamnet (dess mappnamn). I det här exemplet definieras funktionen i sökvägen /ordertill . Värden skickar en HTTP-begäran till den anpassade hanteraren på sökvägen /ordertill .
När du skickar POST begäranden till den här funktionen är utlösardata och funktionsmetadata tillgängliga via HTTP-begärandetexten. Du kan komma åt den ursprungliga HTTP-begärandetexten i nyttolastens Data.req.Body.
Funktionens svar formateras till nyckel/värde-par där Outputs medlemmen har ett JSON-värde där nycklarna matchar utdata enligt definitionen i filen function.json .
Det här är ett exempel på nyttolast som den här hanteraren returnerar till Functions-värden.
{
"Outputs": {
"message": "{\"id\":1005,\"quantity\":2,\"color\":\"black\"}",
"res": {
"body": "Order enqueued"
}
},
"Logs": null,
"ReturnValue": null
}
Genom att ange message utdata som är lika med de orderdata som kom in från begäran, matar funktionen ut data som beställer data till den konfigurerade kön. Functions-värden returnerar också DET HTTP-svar som konfigurerats i res till anroparen.
Funktionen ENDAST HTTP
För HTTP-utlösta funktioner utan ytterligare bindningar eller utdata kanske du vill att hanteraren ska arbeta direkt med HTTP-begäran och -svaret i stället för de anpassade request och response-nyttolasterna. Du kan konfigurera det här beteendet i host.json med hjälp av inställningen enableProxyingHttpRequest som stöder strömning av svar.
Viktigt!
Det primära syftet med funktionen för anpassade hanterare är att aktivera språk och körningsmiljöer som för närvarande inte har förstklassigt stöd för Azure Functions. Även om du kanske kan köra webbprogram med hjälp av anpassade hanterare är Azure Functions inte en omvänd standardproxy. Vissa komponenter i HTTP-begäran, till exempel vissa rubriker och vägar, kan vara begränsade. Ditt program kan också uppleva överdriven kallstart.
Överväg att köra dina webbappar på Azure App Service för att hantera dessa omständigheter.
I följande exempel visas hur du konfigurerar en HTTP-utlöst funktion utan ytterligare bindningar eller utdata. Scenariot som implementeras i det här exemplet har en funktion med namnet hello som accepterar en GET eller POST .
Implementering
I en mapp med namnet hello konfigurerar function.json-filen den HTTP-utlösta funktionen.
hello/function.json
{
"bindings": [
{
"type": "httpTrigger",
"authLevel": "anonymous",
"direction": "in",
"name": "req",
"methods": ["get", "post"]
},
{
"type": "http",
"direction": "out",
"name": "res"
}
]
}
Funktionen är konfigurerad för att acceptera både GET och POST begäranden, och resultatvärdet anges via ett argument med namnet res.
I appens rot är host.json-filen konfigurerad att köras handler.exe och enableProxyingHttpRequest är inställd på true.
{
"version": "2.0",
"customHandler": {
"description": {
"defaultExecutablePath": "handler.exe"
},
"enableProxyingHttpRequest": true
}
}
Följande är en POST-begäran till Functions-värden. Functions-värden skickar sedan begäran till den anpassade hanteraren.
POST http://127.0.0.1:7071/api/hello HTTP/1.1
Content-Type: application/json
{
"message": "Hello World!"
}
Filen handler.go implementerar en webbserver och HTTP-funktion.
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))
}
I det här exemplet skapar den anpassade hanteraren en webbserver för att hantera HTTP-händelser och lyssnar efter begäranden via FUNCTIONS_CUSTOMHANDLER_PORT.
GET begäranden hanteras genom att returnera en sträng och POST begäranden har åtkomst till begärandetexten.
Vägen för orderfunktionen här är /api/hello, samma som den ursprungliga begäran.
Kommentar
FUNCTIONS_CUSTOMHANDLER_PORT är inte den port som är synlig för allmänheten som används för att anropa funktionen. Functions-värden använder den här porten för att anropa den anpassade hanteraren.
Distribuera
Du kan distribuera en anpassad hanterare till varje värdalternativ för Azure Functions. Om hanteraren kräver operativsystem- eller plattformsberoenden (till exempel en språkkörning) kan du behöva använda en anpassad container.
När du skapar en funktionsapp i Azure för anpassade hanterare väljer du .NET Core som stack.
Kör följande kommando för att distribuera en anpassad hanteringsapp med hjälp av Azure Functions Core Tools.
func azure functionapp publish $functionAppName
Kommentar
Kontrollera att alla filer som krävs för att köra din anpassade hanterare finns i mappen och ingår i distributionen. Om din anpassade hanterare är binär körbar eller har plattformsspecifika beroenden kontrollerar du att filerna matchar måldistributionsplattformen.
Begränsningar
- Webbservern för anpassad hanterare måste starta inom 60 sekunder.
Exempel
Exempel på hur du implementerar funktioner på olika språk finns i GitHub-lagringsplatsen för anpassade hanterarexempel.
Felsökning och support
Spårningsloggning
Om din anpassade hanteringsprocess inte startar eller om den har problem med att kommunicera med Functions-värden ökar du funktionsappens loggnivå till att Trace se fler diagnostiska meddelanden från värden.
Om du vill ändra funktionsappens standardloggnivå konfigurerar du logLevel inställningen i logging avsnittet i host.json.
{
"version": "2.0",
"customHandler": {
"description": {
"defaultExecutablePath": "handler.exe"
}
},
"logging": {
"logLevel": {
"default": "Trace"
}
}
}
Värden för Functions matar ut extra loggmeddelanden, inklusive information som rör den anpassade hanteringsprocessen. Använd loggarna för att undersöka problem med att starta din anpassade hanteringsprocess eller anropa funktioner i din anpassade hanterare.
Lokalt skrivs loggar ut till konsolen.
I Azure kör du frågor mot Application Insights-spårningar för att visa loggmeddelandena. Om din app skapar en stor mängd loggar skickas endast en delmängd loggmeddelanden till Application Insights. Inaktivera sampling för att säkerställa att alla meddelanden loggas.
Testa anpassad hanterare isolerat
Anpassade hanteringsappar är webbserverprocesser, så det kan vara bra att starta dem på egen hand och testa funktionsanrop genom att skicka falska HTTP-begäranden. Om du vill skicka HTTP-begäranden med nyttolaster måste du välja ett verktyg som skyddar dina data. Mer information finns i HTTP-testverktyg.
Du kan också använda den här strategin i DINA CI/CD-pipelines för att köra automatiserade tester på din anpassade hanterare.
Körningsmiljö
Anpassade hanterare körs i samma miljö som en typisk Azure Functions-app. Testa hanteraren för att se till att miljön innehåller alla beroenden som den behöver köra. För appar som kräver ytterligare beroenden kan du behöva köra dem med hjälp av en anpassad containeravbildning som finns i Azure Functions Premium-planen.
Få support
Om du behöver hjälp med en funktionsapp med anpassade hanterare kan du skicka en begäran via vanliga supportkanaler. Men på grund av de många olika språk som används för att skapa anpassade hanterarappar är stödet inte obegränsat.
Stöd är tillgängligt om Functions-värden har problem med att starta eller kommunicera med den anpassade hanteringsprocessen. För problem som är specifika för det inre arbetet i din anpassade hanteringsprocess, till exempel problem med det valda språket eller ramverket, kan vårt supportteam inte ge hjälp i den här kontexten.
Nästa steg
Kom igång skapa en Azure Functions-app i Go eller Rust med snabbstarten för anpassade hanterare.