Sdílet prostřednictvím


Vlastní obslužné rutiny Azure Functions

Azure Functions spouští kód aplikace pomocí obslužných rutin specifických pro jazyk. Tyto obslužné rutiny specifické pro jazyk umožňují službě Functions ve výchozím nastavení podporovat většinu klíčových jazyků . Možná ale budete muset spustit kód v jiném jazyce nebo balíčku.

Vlastní obslužné rutiny jsou odlehčené webové servery, které přijímají události z hostitelského procesu v Azure Functions. Vlastní obslužné rutiny můžete použít k nasazení do Azure Functions libovolný projekt kódu, který podporuje primitivy HTTP.

Vlastní obslužné rutiny jsou nejvhodnější pro situace, kdy chcete:

  • Implementujte funkční aplikaci v jazyce, který není aktuálně k dispozici jako předem připravený, například Go nebo Rust.
  • Implementujte aplikaci funkcí v modulu runtime, který aktuálně není ve výchozím nastavení doporučený, například Deno.
  • Nasaďte server vytvořený pomocí standardních sad SDK MCP do Azure Functions.

Pomocí vlastních obslužných rutin můžete pomocí sad rozšíření použít triggery a vstupní a výstupní vazby.

Začínáme s vlastními obslužnými rutinami Azure Functions pomocí rychlých startů v Go a Rustu

Přehled

Následující diagram znázorňuje vztah mezi hostitelem služby Functions a webovým serverem implementovaným jako vlastní obslužná rutina.

Přehled vlastní obslužné rutiny Azure Functions

  1. Každá událost aktivuje požadavek odeslaný hostiteli Functions. Událost je jakákoli aktivační událost, kterou Azure Functions podporuje.
  2. Hostitel služby Functions pak vydá datovou část požadavku na webový server. Datová část obsahuje data triggeru a vstupní vazby a další metadata funkce.
  3. Webový server spustí jednotlivé funkce a vrátí datovou část odpovědi hostiteli Functions.
  4. Hostitel Functions předává data z odpovědi na výstupní vazby funkce ke zpracování.

Aplikace Azure Functions implementovaná jako vlastní obslužná rutina musí nakonfigurovat host.json, local.settings.json a function.json soubory podle několika konvencí.

Nasazení serverů MCP v místním prostředí

Vlastní obslužné rutiny také umožňují hostovat servery MCP, které sestavujete pomocí oficiálních sad SDK MCP ve službě Azure Functions. Vlastní obslužné rutiny poskytují jednoduché a zjednodušené prostředí pro hostování serverů MCP v Azure. Další informace najdete v tématu Místní vzdálený server MCP ve službě Azure Functions.

Poznámka:

Možnost hostovat na Azure Functions servery MCP, které vytvoříte pomocí oficiálních sad MCP SDK, je nyní ve verzi preview.

Struktura aplikace

K implementaci vlastní obslužné rutiny potřebuje vaše aplikace následující aspekty:

  • Soubor host.json v kořenovém adresáři aplikace
  • Soubor local.settings.json v kořenovém adresáři aplikace
  • Soubor function.json pro každou funkci (uvnitř složky, která odpovídá názvu funkce)
  • Příkaz, skript nebo spustitelný soubor, který spouští webový server

Následující diagram ukazuje, jak tyto soubory vypadají v systému souborů pro funkci s názvem "MyQueueFunction" a vlastní spustitelný soubor obslužné rutiny s názvem handler.exe.

| /MyQueueFunction
|   function.json
|
| host.json
| local.settings.json
| handler.exe

Konfigurace

Aplikaci nakonfigurujete prostřednictvím host.json a local.settings.json souborů.

host.json

host.json směruje hostitele Functions na místo, kde odesílat požadavky odkazováním na webový server, který může zpracovávat události HTTP.

Definujte vlastní obslužnou rutinu tak, že nakonfigurujete soubor host.json s podrobnostmi o tom, jak webový server spustit prostřednictvím oddílu customHandler .

{
  "version": "2.0",
  "customHandler": {
    "description": {
      "defaultExecutablePath": "handler.exe"
    }
  }
}

Oddíl customHandler odkazuje na cíl definovaný objektem defaultExecutablePath. Cílem spuštění může být příkaz, spustitelný soubor nebo soubor, ve kterém je webový server implementovaný.

arguments Pomocí pole předejte spustitelnému souboru všechny argumenty. Argumenty umožňují rozšíření proměnných prostředí (nastavení aplikace) pomocí zápisu %%.

Můžete také změnit pracovní adresář používaný spustitelným souborem s workingDirectory.

{
  "version": "2.0",
  "customHandler": {
    "description": {
      "defaultExecutablePath": "app/handler.exe",
      "arguments": [
        "--database-connection-string",
        "%DATABASE_CONNECTION_STRING%"
      ],
      "workingDirectory": "app"
    }
  }
}
Podpora vazeb

Standardní triggery spolu se vstupními a výstupními vazbami jsou k dispozici odkazováním na sady rozšíření v souboru host.json .

local.settings.json

local.settings.json definuje nastavení aplikace používané při místním spuštění aplikace funkcí. Protože může obsahovat tajné kódy, vylučte local.settings.json ze správy zdrojového kódu. V Azure místo toho použijte nastavení aplikace.

U vlastních obslužných rutin nastavte FUNCTIONS_WORKER_RUNTIME hodnotu Custom v local.settings.json.

{
  "IsEncrypted": false,
  "Values": {
    "FUNCTIONS_WORKER_RUNTIME": "Custom"
  }
}

Metadata funkcí

Při použití vlastní obslužné rutiny jsou obsah function.json stejný jako při definování funkce v jakémkoli jiném kontextu. Jediným požadavkem je umístit function.json soubory do složky s názvem, aby odpovídaly názvu funkce.

Následující function.json konfiguruje funkci, která má aktivační událost fronty a výstupní vazbu fronty. Protože je ve složce s názvem MyQueueFunction, definuje funkci s názvem 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"
    }
  ]
}

Datová část žádosti

Když hostitel Functions obdrží zprávu ve frontě, odešle požadavek HTTP post vlastnímu zpracovateli s datovou částí.

Následující kód ukazuje příklad požadovaného payloadu. Datová část obsahuje strukturu JSON se dvěma členy: Data a Metadata.

Člen Data obsahuje klíče, které odpovídají názvům vstupních a aktivačních událostí definovaným v poli vazeb v souboru function.json .

Člen Metadata obsahuje metadata generovaná ze zdroje událostí.

{
  "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"
    }
  }
}

Datová část odpovědi

Podle konvence jsou odpovědi funkcí formátované jako páry klíč/hodnota. Mezi podporované klíče patří:

Klíč datové části Datový typ Poznámky
Outputs objekt Obsahuje hodnoty odpovědí definované polem bindings v function.json.

Pokud je například funkce nakonfigurovaná s výstupní vazbou fronty s názvem myQueueOutput, obsahuje Outputs klíč s názvem myQueueOutput, který vlastní obslužná rutina nastaví na zprávy, které odesílá do fronty.
Logs pole Zprávy, které se zobrazují v protokolech volání funkcí

Při spuštění v Azure se zprávy zobrazí v Application Insights.
ReturnValue řetězec Slouží k poskytnutí odpovědi, když je výstup nakonfigurovaný jako $return v souboru function.json .

Tato tabulka ukazuje příklad nákladu odpovědi.

{
  "Outputs": {
    "res": {
      "body": "Message enqueued"
    },
    "myQueueOutput": [
      "queue message 1",
      "queue message 2"
    ]
  },
  "Logs": [
    "Log message 1",
    "Log message 2"
  ],
  "ReturnValue": "{\"hello\":\"world\"}"
}

Příklady

Vlastní obslužné rutiny můžete implementovat v libovolném jazyce, který podporuje příjem událostí HTTP. Následující příklady ukazují, jak implementovat vlastní obslužnou rutinu pomocí programovacího jazyka Go.

Funkce s vazbami

Tento příklad ukazuje funkci s názvem order , která přijímá požadavek s datovou POST částí představující objednávku produktu. Když do funkce publikujete objednávku, vytvoří se zpráva Queue Storage a vrátí odpověď HTTP.

Implementace

Ve složce s názvem pořadí nakonfiguruje soubor function.json funkci aktivovanou protokolem 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"
    }
  ]
}

Tato funkce je definována jako funkce aktivovaná protokolem HTTP, která vrací odpověď HTTP a vypíše zprávu queue storage.

V kořenovém adresáři aplikace je soubor host.json nakonfigurovaný tak, aby spustil spustitelný soubor s názvem handler.exe (handlerv Linuxu nebo macOS).

{
  "version": "2.0",
  "customHandler": {
    "description": {
      "defaultExecutablePath": "handler.exe"
    }
  },
  "extensionBundle": {
    "id": "Microsoft.Azure.Functions.ExtensionBundle",
    "version": "[4.*, 5.0.0)"
  }
}

Toto je požadavek HTTP odeslaný do modulu runtime služby Functions.

POST http://127.0.0.1:7071/api/order HTTP/1.1
Content-Type: application/json

{
  "id": 1005,
  "quantity": 2,
  "color": "black"
}

Modul runtime služby Functions odešle vlastní obslužné rutině následující požadavek 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": {
  }
}

Poznámka:

Některé části datové části byly odebrány kvůli stručnosti.

handler.exe je zkompilovaný program vlastní obslužné rutiny Go, který spouští webový server a reaguje na žádosti o vyvolání funkcí z hostitele služby Functions.

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))
}

V tomto příkladu vlastní obslužná rutina spustí webový server pro zpracování událostí HTTP a naslouchá požadavkům prostřednictvím FUNCTIONS_CUSTOMHANDLER_PORT.

I když hostitel Functions obdrží původní požadavek HTTP na /api/order, vyvolá vlastní obslužnou rutinu pomocí názvu funkce (její název složky). V tomto příkladu je funkce definována na cestě /order. Hostitel odešle vlastní obslužnou rutinu požadavek HTTP na cestu /order.

Při odesílání POST požadavků do této funkce jsou data triggeru a metadata funkce k dispozici prostřednictvím textu požadavku HTTP. V datové části Data.req.Bodymůžete získat přístup k původnímu textu požadavku HTTP .

Odpověď funkce je naformátovaná do párů klíč/hodnota, kde Outputs člen obsahuje hodnotu JSON, ve které klíče odpovídají výstupům definovaným v souboru function.json .

Toto je příklad datové části, kterou tato obslužná rutina vrátí hostiteli Functions.

{
  "Outputs": {
    "message": "{\"id\":1005,\"quantity\":2,\"color\":\"black\"}",
    "res": {
      "body": "Order enqueued"
    }
  },
  "Logs": null,
  "ReturnValue": null
}

Nastavením výstupu message se rovná datům pořadí, která přišla z požadavku, funkce vypíše data objednávky do nakonfigurované fronty. Hostitel Functions také vrátí odpověď HTTP nakonfigurovanou res volajícímu.

Funkce pouze HTTP

U funkcí aktivovaných protokolem HTTP bez dalších vazeb nebo výstupů je možné chtít, aby obslužná rutina pracovala přímo s požadavkem a odpovědí HTTP, místo aby používala vlastní obslužnou rutinu s datovými částmi požadavku request a odpovědi response. Toto chování můžete nakonfigurovat v host.json pomocí enableProxyingHttpRequest nastavení, které podporuje streamování odpovědí.

Důležité

Primárním účelem funkce vlastních obslužných rutin je povolit jazyky a moduly runtime, které v současné době nemají prvotřídní podporu ve službě Azure Functions. I když možná budete moct spouštět webové aplikace pomocí vlastních obslužných rutin, Azure Functions není standardní reverzní proxy server. Některé součásti požadavku HTTP, například určité hlavičky a trasy, můžou být omezené. U vaší aplikace může docházet také k nadměrnému studenému startu.

Pokud chcete tyto okolnosti vyřešit, zvažte spuštění webových aplikací ve službě Aplikace Azure Service.

Následující příklad ukazuje, jak nakonfigurovat funkci aktivovanou protokolem HTTP bez dalších vazeb nebo výstupů. Scénář implementovaný v tomto příkladu obsahuje funkci s názvem hello nebo GETPOST .

Implementace

Ve složce s názvem hello nakonfiguruje soubor function.json funkci aktivovanou protokolem HTTP.

hello/function.json

{
  "bindings": [
    {
      "type": "httpTrigger",
      "authLevel": "anonymous",
      "direction": "in",
      "name": "req",
      "methods": ["get", "post"]
    },
    {
      "type": "http",
      "direction": "out",
      "name": "res"
    }
  ]
}

Funkce je nakonfigurována tak, aby přijímala obě GET požadavky POST a výsledná hodnota je poskytována prostřednictvím argumentu s názvem res.

V kořenovém adresáři aplikace je soubor host.json nakonfigurovaný ke spuštění handler.exe a enableProxyingHttpRequest je nastavený na true.

{
  "version": "2.0",
  "customHandler": {
    "description": {
      "defaultExecutablePath": "handler.exe"
    },
    "enableProxyingHttpRequest": true
  }
}

Následuje požadavek POST na hostitele služby Functions. Hostitel Functions pak odešle požadavek vlastní obslužné rutině.

POST http://127.0.0.1:7071/api/hello HTTP/1.1
Content-Type: application/json

{
  "message": "Hello World!"
}

Soubor handler.go implementuje webový server a funkci 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))
}

V tomto příkladu vlastní obslužná rutina vytvoří webový server pro zpracování událostí HTTP a naslouchá požadavkům prostřednictvím FUNCTIONS_CUSTOMHANDLER_PORT.

GET požadavky se zpracovávají vrácením řetězce a POST požadavky mají přístup k textu požadavku.

Trasa pro funkci objednávky je /api/hellostejná jako původní požadavek.

Poznámka:

Nejedná se o veřejný port FUNCTIONS_CUSTOMHANDLER_PORT používaný k volání funkce. Hostitel služby Functions používá tento port k volání vlastní obslužné rutiny.

Nasazování

Vlastní obslužnou rutinu můžete nasadit do každé možnosti hostování Azure Functions. Pokud vaše obslužná rutina vyžaduje závislosti operačního systému nebo platformy (například modul runtime jazyka), možná budete muset použít vlastní kontejner.

Když v Azure vytvoříte aplikaci funkcí pro vlastní obslužné rutiny, vyberte jako zásobník .NET Core.

Pokud chcete nasadit vlastní aplikaci obslužné rutiny pomocí nástrojů Azure Functions Core Tools, spusťte následující příkaz.

func azure functionapp publish $functionAppName

Poznámka:

Ujistěte se, že všechny soubory potřebné ke spuštění vlastní obslužné rutiny jsou ve složce a jsou součástí nasazení. Pokud je vaše vlastní obslužná rutina binární spustitelný soubor nebo má závislosti specifické pro platformu, ujistěte se, že tyto soubory odpovídají cílové platformě nasazení.

Omezení

  • Webový server vlastní obslužné rutiny se musí spustit do 60 sekund.

Ukázky

Příklady implementace funkcí v různých jazycích najdete v ukázkách vlastních obslužných rutin v úložišti GitHub.

Řešení potíží a podpora

Protokolování trasování

Pokud se váš vlastní proces obslužné rutiny nepodaří spustit nebo pokud má problémy s komunikací s hostitelem Functions, zvyšte úroveň protokolu aplikace Function na Trace a zobrazí se další diagnostické zprávy z hostitele.

Pokud chcete změnit výchozí úroveň protokolu aplikace funkcí, nakonfigurujte logLevel nastavení v logging části host.json.

{
  "version": "2.0",
  "customHandler": {
    "description": {
      "defaultExecutablePath": "handler.exe"
    }
  },
  "logging": {
    "logLevel": {
      "default": "Trace"
    }
  }
}

Služba Functions generuje extra zprávy protokolu, včetně informací souvisejících s vlastním obslužným procesem. Pomocí protokolů můžete prozkoumat problémy se spuštěním vlastního procesu obslužné rutiny nebo vyvoláním funkcí ve vlastní obslužné rutině.

Místně se protokoly vytisknou do konzoly.

V Azure se dotazujte na trasování Application Insights, aby se zobrazily zprávy protokolu. Pokud vaše aplikace vytváří velký objem protokolů, do Application Insights se odešle jenom podmnožina zpráv protokolu. Zakažte vzorkování , aby se zajistilo, že jsou protokolované všechny zprávy.

Testování vlastní obslužné rutiny v izolaci

Vlastní aplikace obslužné rutiny jsou procesy webového serveru, takže může být užitečné je spustit samostatně a otestovat vyvolání funkcí odesláním simulovaných požadavků HTTP. Pro odesílání požadavků HTTP s datovými částmi nezapomeňte zvolit nástroj, který udržuje vaše data v bezpečí. Další informace najdete v tématu Nástroje pro testování HTTP.

Tuto strategii můžete použít také v kanálech CI/CD ke spouštění automatizovaných testů na vlastní obslužné rutině.

Spouštěcí prostředí

Vlastní obslužné rutiny běží ve stejném prostředí jako typická aplikace Azure Functions. Otestujte obslužnou rutinu a ujistěte se, že prostředí obsahuje všechny závislosti, které potřebuje ke spuštění. U aplikací, které vyžadují další závislosti, je možné, že je budete muset spustit pomocí vlastní image kontejneru hostované v plánu Azure Functions Premium.

Získání podpory

Pokud potřebujete pomoc s aplikací funkcí s vlastními obslužnými rutinami, můžete odeslat žádost prostřednictvím běžných kanálů podpory. Vzhledem k široké škále možných jazyků používaných k vytváření vlastních aplikací obslužných rutin ale podpora není neomezená.

Podpora je dostupná, pokud má hostitel služby Functions problémy se spuštěním nebo komunikací s vlastním procesem obslužné rutiny. V případě problémů specifických pro vnitřní fungování vašeho vlastního procesu obslužné rutiny, jako jsou problémy s vybraným jazykem nebo architekturou, nemůže náš tým podpory v tomto kontextu poskytnout pomoc.

Další kroky

Začněte vytvářet aplikaci Azure Functions v Go nebo Rust pomocí rychlého startu vlastních obslužných rutin.