Egyéni kezelők az Azure Functionshöz
Minden Functions-alkalmazást egy nyelvspecifikus kezelő hajt végre. Bár az Azure Functions alapértelmezés szerint számos nyelvkezelőt tartalmaz, előfordulhat, hogy más nyelveket vagy futtatókörnyezeteket szeretne használni.
Az egyéni kezelők egyszerű webkiszolgálók, amelyek eseményeket fogadnak a Functions-gazdagéptől. A HTTP-primitíveket támogató bármely nyelv implementálhat egyéni kezelőt.
Az egyéni kezelők a legmegfelelőbbek azokhoz a helyzetekhez, amikor a következőkre van szüksége:
- Függvényalkalmazás implementálása olyan nyelven, amely jelenleg nem érhető el, például Go vagy Rust.
- Olyan függvényalkalmazás implementálása olyan futtatókörnyezetben, amely jelenleg nem szerepel alapértelmezés szerint, például a Deno.
Az egyéni kezelők segítségével triggereket, valamint bemeneti és kimeneti kötéseket használhat bővítménykötegeken keresztül.
Ismerkedés az Azure Functions egyéni kezelőivel a Go and Rust rövid útmutatóival.
Áttekintés
Az alábbi ábra a Functions-gazdagép és az egyéni kezelőként implementált webkiszolgáló közötti kapcsolatot mutatja be.
- Minden esemény elindít egy, a Functions-gazdagépnek küldött kérést. Az esemény minden olyan eseményindító, amelyet az Azure Functions támogat.
- A Functions-gazdagép ezután egy hasznos adatkérést ad ki a webkiszolgálónak. A hasznos adatok trigger- és bemeneti kötési adatokat, valamint a függvény egyéb metaadatait tárolják.
- A webkiszolgáló végrehajtja az egyes függvényeket , és válasz hasznos adatokat ad vissza a Functions-gazdagépnek.
- A Functions-gazdagép adatokat ad át a válaszból a függvény kimeneti kötéseinek feldolgozásra.
Az egyéni kezelőként implementált Azure Functions-alkalmazásoknak néhány konvenció szerint kell konfigurálnia a host.json, local.settings.json és function.json fájlokat.
Alkalmazásstruktúra
Egyéni kezelő implementálásához az alábbi szempontokra van szüksége az alkalmazáshoz:
- Egy host.json fájl az alkalmazás gyökerénél
- Egy local.settings.json fájl az alkalmazás gyökerénél
- Az egyes függvények function.json fájlja (a függvénynévnek megfelelő mappában)
- Webkiszolgálót futtató parancs, szkript vagy végrehajtható
Az alábbi ábra bemutatja, hogyan jelennek meg ezek a fájlok a fájlrendszeren a "MyQueueFunction" nevű függvényhez és egy handler.exe nevű egyéni kezelőhöz.
| /MyQueueFunction
| function.json
|
| host.json
| local.settings.json
| handler.exe
Konfiguráció
Az alkalmazás a host.json és local.settings.json fájlokon keresztül van konfigurálva.
host.json
host.json megadja a Functions-gazdagépnek, hogy hová küldjön kéréseket egy HTTP-események feldolgozására képes webkiszolgálóra mutatva.
Az egyéni kezelő a host.json fájl konfigurálásával határozható meg, amely részletesen bemutatja, hogyan futtatható a webkiszolgáló a customHandler
szakaszon keresztül.
{
"version": "2.0",
"customHandler": {
"description": {
"defaultExecutablePath": "handler.exe"
}
}
}
A customHandler
szakasz egy célra mutat a defaultExecutablePath
. A végrehajtási cél lehet parancs, végrehajtható vagy fájl, amelyben a webkiszolgáló implementálva van.
arguments
A tömb használatával bármilyen argumentumot átadhat a végrehajthatónak. Az argumentumok támogatják a környezeti változók (alkalmazásbeállítások) jelöléssel történő %%
bővítését.
A végrehajtható fájl által használt munkakönyvtárat is módosíthatja a következővel workingDirectory
: .
{
"version": "2.0",
"customHandler": {
"description": {
"defaultExecutablePath": "app/handler.exe",
"arguments": [
"--database-connection-string",
"%DATABASE_CONNECTION_STRING%"
],
"workingDirectory": "app"
}
}
}
A kötések támogatása
A standard triggerek, valamint a bemeneti és kimeneti kötések a host.json fájl bővítménycsomagjaira hivatkozva érhetők el.
local.settings.json
local.settings.json a függvényalkalmazás helyi futtatásakor használt alkalmazásbeállításokat határozza meg. Mivel titkos kulcsokat tartalmazhat, local.settings.json ki kell zárni a forráskövetésből. Az Azure-ban használja inkább az alkalmazásbeállításokat.
Egyéni kezelők esetén állítsa be FUNCTIONS_WORKER_RUNTIME
a Custom
local.settings.json.
{
"IsEncrypted": false,
"Values": {
"FUNCTIONS_WORKER_RUNTIME": "Custom"
}
}
Függvény metaadatai
Ha egyéni kezelővel használja, a function.json tartalma nem különbözik attól, ahogyan egy függvényt bármilyen más környezetben definiálna. Az egyetlen követelmény, hogy function.json fájloknak a függvény nevével egyező nevű mappában kell lenniük.
Az alábbi function.json egy üzenetsor-eseményindítóval és üzenetsorkimeneti kötéssel rendelkező függvényt konfigurál. Mivel egy MyQueueFunction nevű mappában található, egy MyQueueFunction nevű függvényt definiál.
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"
}
]
}
Hasznos adatok kérése
Üzenetsor érkezésekor a Functions-gazdagép http-post kérést küld az egyéni kezelőnek a törzs hasznos adataival.
Az alábbi kód egy mintakérés hasznos adatait jelöli. A hasznos adat egy JSON-struktúrát tartalmaz, amelynek két tagja van: Data
és Metadata
.
A Data
tag olyan kulcsokat tartalmaz, amelyek megfelelnek a bemeneti és triggerneveknek a function.json fájl kötéstömbjében meghatározottak szerint.
A Metadata
tag tartalmazza az eseményforrásból létrehozott metaadatokat.
{
"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"
}
}
}
Válasz hasznos adatai
Konvenció szerint a függvényválaszok kulcs-érték párokként vannak formázva. A támogatott kulcsok a következők:
Adattípus | Megjegyzések | |
---|---|---|
Outputs |
object | A function.json tömb által bindings meghatározott válaszértékeket tartalmazza.Ha például egy függvény "myQueueOutput" nevű üzenetsorkimeneti kötéssel van konfigurálva, akkor Outputs az egyéni kezelő által az üzenetsorba küldött üzenetekhez beállított kulcsot myQueueOutput tartalmazza. |
Logs |
array | Az üzenetek megjelennek a Függvények meghívási naplóiban. Az Azure-ban való futtatáskor üzenetek jelennek meg az Application Insightsban. |
ReturnValue |
húr | Válasz megadására szolgál, ha a kimenet a function.json fájlhoz hasonlóan $return van konfigurálva. |
Ez egy példa a válasz hasznos adataira.
{
"Outputs": {
"res": {
"body": "Message enqueued"
},
"myQueueOutput": [
"queue message 1",
"queue message 2"
]
},
"Logs": [
"Log message 1",
"Log message 2"
],
"ReturnValue": "{\"hello\":\"world\"}"
}
Példák
Az egyéni kezelők bármely olyan nyelven implementálhatók, amely támogatja a HTTP-események fogadását. Az alábbi példák bemutatják, hogyan implementálhat egyéni kezelőt a Go programozási nyelv használatával.
Függvény kötésekkel
Az ebben a példában implementált forgatókönyv egy olyan függvényt order
tartalmaz, amely egy termékrendelést jelképező hasznos adattal rendelkező függvényt fogad el POST
. A függvény megrendelésének közzétételekor létrejön egy Üzenetsortár üzenet, és a rendszer HTTP-választ ad vissza.
Megvalósítás
Egy névvel ellátott mappában a function.json fájl konfigurálja a HTTP-aktivált függvényt.
rendelés/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"
}
]
}
Ez a függvény HTTP-aktivált függvényként van definiálva, amely HTTP-választ ad vissza, és üzenetsortár-üzenetet ad ki.
Az alkalmazás gyökerénél a host.json fájl úgy van konfigurálva, hogy futtasson egy végrehajtható fájlt handler.exe
(handler
Linuxon vagy macOS-en).
{
"version": "2.0",
"customHandler": {
"description": {
"defaultExecutablePath": "handler.exe"
}
},
"extensionBundle": {
"id": "Microsoft.Azure.Functions.ExtensionBundle",
"version": "[1.*, 2.0.0)"
}
}
Ez a Függvények futtatókörnyezetnek küldött HTTP-kérés.
POST http://127.0.0.1:7071/api/order HTTP/1.1
Content-Type: application/json
{
"id": 1005,
"quantity": 2,
"color": "black"
}
A Functions-futtatókörnyezet ezután a következő HTTP-kérést küldi el az egyéni kezelőnek:
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": {
}
}
Feljegyzés
A hasznos adatok bizonyos részeit eltávolították a rövidség kedvéért.
handler.exe a lefordított Go egyéni kezelőprogram, amely webkiszolgálót futtat, és válaszol a Functions-gazdagép függvényhívási kérelmeire.
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))
}
Ebben a példában az egyéni kezelő egy webkiszolgálót futtat a HTTP-események kezeléséhez, és a kérések figyelésére van beállítva a FUNCTIONS_CUSTOMHANDLER_PORT
.
Annak ellenére, hogy a Functions-gazdagép eredeti HTTP-kérést /api/order
kapott, meghívja az egyéni kezelőt a függvény neve (mappaneve) használatával. Ebben a példában a függvény az elérési úton /order
van definiálva. A gazdagép HTTP-kérést küld az egyéni kezelőnek /order
a következő útvonalon: .
Amikor POST
a rendszer kéréseket küld a függvénynek, az eseményindító adatai és a függvény metaadatai a HTTP-kérés törzsén keresztül érhetők el. Az eredeti HTTP-kérelemtörzs a hasznos adatokban Data.req.Body
érhető el.
A függvény válasza kulcs/érték párokra van formázva, ahol a Outputs
tag egy JSON-értéket tárol, ahol a kulcsok megegyeznek a function.json fájlban meghatározott kimenetekkel.
Ez egy példa hasznos adatra, amelyet a kezelő visszatér a Functions-gazdagéphez.
{
"Outputs": {
"message": "{\"id\":1005,\"quantity\":2,\"color\":\"black\"}",
"res": {
"body": "Order enqueued"
}
},
"Logs": null,
"ReturnValue": null
}
A kérelemből kapott rendelési adatokkal egyenlő kimenet beállításával message
a függvény az adatokat a konfigurált üzenetsorba rendezi. A Functions-gazdagép a hívónak konfigurált res
HTTP-választ is visszaadja.
CSAK HTTP-függvény
A HTTP által aktivált, további kötések és kimenetek nélkül működő függvények esetében előfordulhat, hogy a kezelő közvetlenül a HTTP-kéréssel és a válaszsal dolgozik az egyéni kezelői kérések és válaszok hasznos adatai helyett. Ez a viselkedés konfigurálható host.json a enableForwardingHttpRequest
beállítás használatával.
Fontos
Az egyéni kezelők funkció elsődleges célja olyan nyelvek és futtatókörnyezetek engedélyezése, amelyek jelenleg nem rendelkeznek első osztályú támogatással az Azure Functionsben. Bár lehet, hogy webalkalmazásokat is futtathat egyéni kezelőkkel, az Azure Functions nem szabványos fordított proxy. Egyes funkciók, például a válaszstreamelés, a HTTP/2 és a WebSocket nem érhetők el. A HTTP-kérés egyes összetevői, például bizonyos fejlécek és útvonalak korlátozottak lehetnek. Előfordulhat, hogy az alkalmazás túlzott hidegindítást is tapasztal.
E körülmények kezelése érdekében fontolja meg a webalkalmazások Azure-alkalmazás Szolgáltatáson való futtatását.
Az alábbi példa bemutatja, hogyan konfigurálhat EGY HTTP-aktivált függvényt további kötések és kimenetek nélkül. Az ebben a példában implementált forgatókönyv egy olyan függvényt hello
tartalmaz, amely egy vagy POST
több függvényt GET
fogad el.
Megvalósítás
A hello nevű mappában a function.json fájl konfigurálja a HTTP-aktivált függvényt.
hello/function.json
{
"bindings": [
{
"type": "httpTrigger",
"authLevel": "anonymous",
"direction": "in",
"name": "req",
"methods": ["get", "post"]
},
{
"type": "http",
"direction": "out",
"name": "res"
}
]
}
A függvény úgy van konfigurálva, hogy fogadja el a kéréseket GET
és POST
a kéréseket, és az eredmény értékét egy nevesített res
argumentumon keresztül adja meg.
Az alkalmazás gyökerénél a host.json fájl úgy van konfigurálva, hogy futjon handler.exe
, és enableForwardingHttpRequest
a következőre true
van állítva.
{
"version": "2.0",
"customHandler": {
"description": {
"defaultExecutablePath": "handler.exe"
},
"enableForwardingHttpRequest": true
}
}
Ha enableForwardingHttpRequest
igen true
, a csak HTTP-függvények viselkedése eltér az alapértelmezett egyéni kezelők viselkedésétől az alábbi módokon:
- A HTTP-kérés nem tartalmazza az egyéni kezelők hasznos adatait. Ehelyett a Functions-gazdagép meghívja a kezelőt az eredeti HTTP-kérés másolatával.
- A Functions-gazdagép az eredeti kéréssel megegyező elérési úttal hívja meg a kezelőt, beleértve a lekérdezési sztring paramétereit is.
- A Functions-gazdagép az eredeti kérésre adott válaszként visszaadja a kezelő HTTP-válaszának egy példányát.
Az alábbiakban egy POST-kérést küldünk a Functions-gazdagépnek. A Functions-gazdagép ezután elküldi a kérés másolatát az egyéni kezelőnek ugyanazon az útvonalon.
POST http://127.0.0.1:7071/api/hello HTTP/1.1
Content-Type: application/json
{
"message": "Hello World!"
}
A fájlkezelő.go fájl webkiszolgálót és HTTP-függvényt implementál.
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))
}
Ebben a példában az egyéni kezelő létrehoz egy webkiszolgálót a HTTP-események kezeléséhez, és a kérések figyelésére van beállítva a FUNCTIONS_CUSTOMHANDLER_PORT
.
GET
a kérelmeket egy sztring visszaadásával kezeli a rendszer, a kérések pedig POST
hozzáférnek a kérelem törzséhez.
A rendelési függvény útvonala megegyezik /api/hello
az eredeti kéréssel.
Feljegyzés
Ez FUNCTIONS_CUSTOMHANDLER_PORT
nem a függvény meghívásához használt nyilvános port. Ezt a portot használja a Functions-gazdagép az egyéni kezelő meghívásához.
Üzembe helyezés
Az egyéni kezelők minden Azure Functions-üzemeltetési beállításban üzembe helyezhetők. Ha a kezelő operációs rendszer- vagy platformfüggőségeket (például nyelvi futtatókörnyezetet) igényel, előfordulhat, hogy egyéni tárolót kell használnia.
Amikor egyéni kezelők számára hoz létre függvényalkalmazást az Azure-ban, javasoljuk, hogy a .NET Core-t válassza veremként.
Ha egyéni kezelőalkalmazást szeretne üzembe helyezni az Azure Functions Core Tools használatával, futtassa az alábbi parancsot.
func azure functionapp publish $functionAppName
Feljegyzés
Győződjön meg arról, hogy az egyéni kezelő futtatásához szükséges összes fájl megtalálható a mappában, és szerepel az üzembe helyezésben. Ha az egyéni kezelő binárisan végrehajtható, vagy platformspecifikus függőségekkel rendelkezik, győződjön meg arról, hogy ezek a fájlok megfelelnek a cél üzembehelyezési platformnak.
Korlátozások
- Az egyéni kezelő webkiszolgálónak 60 másodpercen belül el kell indulnia.
Példák
Tekintse meg a GitHub-adattár egyéni kezelői mintáit, amelyekből megtudhatja, hogyan implementálhat függvényeket különböző nyelveken.
Hibaelhárítás és támogatás
Nyomkövetési naplózás
Ha az egyéni kezelőfolyamat nem indul el, vagy problémákba ütközik a Functions-gazdagéppel való kommunikáció során, növelheti a függvényalkalmazás naplószintjét, hogy további diagnosztikai üzeneteket jelenítsen Trace
meg a gazdagépről.
A függvényalkalmazás alapértelmezett naplószintjének módosításához konfigurálja a beállítást a logLevel
logging
host.json szakaszában.
{
"version": "2.0",
"customHandler": {
"description": {
"defaultExecutablePath": "handler.exe"
}
},
"logging": {
"logLevel": {
"default": "Trace"
}
}
}
A Functions-gazdagép további naplóüzeneteket ad ki, beleértve az egyéni kezelőfolyamattal kapcsolatos információkat is. A naplók segítségével kivizsgálhatja az egyéni kezelő folyamatának elindításával vagy a függvények egyéni kezelőben való meghívásával kapcsolatos problémákat.
A rendszer helyileg kinyomtatja a naplókat a konzolra.
Az Azure-ban az Application Insights-nyomkövetés lekérdezése a naplóüzenetek megtekintéséhez. Ha az alkalmazás nagy mennyiségű naplót hoz létre, a rendszer csak a naplóüzenetek egy részét küldi el az Application Insightsnak. Tiltsa le a mintavételezést , hogy az összes üzenet naplózva legyen.
Egyéni kezelő tesztelése elkülönítve
Az egyéni kezelőalkalmazások egy webkiszolgálói folyamat, ezért hasznos lehet önállóan elindítani, és tesztelni a függvényhívásokat a szimulált HTTP-kérések küldésével. Ha hasznos adatokkal szeretne HTTP-kéréseket küldeni, ügyeljen arra, hogy olyan eszközt válasszon, amely biztonságosan tartja az adatokat. További információ: HTTP-teszteszközök.
Ezt a stratégiát a CI/CD-folyamatokban is használhatja automatizált tesztek futtatásához az egyéni kezelőn.
Végrehajtási környezet
Az egyéni kezelők ugyanabban a környezetben futnak, mint egy tipikus Azure Functions-alkalmazás. Tesztelje a kezelőt, hogy a környezet tartalmazza-e az összes futtatandó függőséget. A további függőségeket igénylő alkalmazások esetében előfordulhat, hogy azokat az Azure Functions Premium-csomagban üzemeltetett egyéni tárolórendszerkép használatával kell futtatnia.
Támogatás kérése
Ha segítségre van szüksége egy egyéni kezelőkkel rendelkező függvényalkalmazáshoz, a kéréseket rendszeres támogatási csatornákon keresztül küldheti el. Az egyéni kezelőalkalmazások létrehozásához használt nyelvek széles választéka miatt azonban a támogatás nem korlátlan.
A támogatás akkor érhető el, ha a Functions-gazdagépen problémák adódnak az egyéni kezelőfolyamat elindításával vagy kommunikációjával. Az egyéni kezelőfolyamat belső működésével kapcsolatos problémák, például a választott nyelvvel vagy keretrendszerrel kapcsolatos problémák esetén támogatási csapatunk nem tud ebben a környezetben segítséget nyújtani.
Következő lépések
Az egyéni kezelők rövid útmutatójával megkezdheti az Azure Functions-alkalmazások készítését a Go vagy a Rust alkalmazásban.