Megosztás a következőn keresztül:


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.

Az Azure Functions egyéni kezelője – áttekintés

  1. 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.
  2. 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.
  3. A webkiszolgáló végrehajtja az egyes függvényeket , és válasz hasznos adatokat ad vissza a Functions-gazdagépnek.
  4. 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:

Hasznos adatkulcs 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 myQueueOutputtartalmazza.
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/orderkapott, 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 /ordervan definiálva. A gazdagép HTTP-kérést küld az egyéni kezelőnek /ordera 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 resargumentumon 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 truevan á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/helloaz 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.