Skapa en funktion i Linux med en anpassad container

I den här självstudien skapar och distribuerar du din kod till Azure Functions en anpassad Docker-container med hjälp av en Linux-basavbildning. Du använder vanligtvis en anpassad avbildning när dina funktioner kräver en specifik språkversion eller har ett specifikt beroende eller en specifik konfiguration som inte tillhandahålls av den inbyggda avbildningen.

Azure Functions alla språk eller körningar med hjälp av anpassade hanterare. För vissa språk, till exempel det R-programmeringsspråk som används i den här självstudien, måste du installera körningen eller ytterligare bibliotek som beroenden som kräver användning av en anpassad container.

Distribution av funktionskoden i en anpassad Linux-container kräver Premium eller en dedikerad (App Service) planvärd. Den här självstudien medför kostnader för några amerikanska dollar i ditt Azure-konto, vilket du kan minimera genom att rensa resurser när du är klar.

Du kan också använda en standardcontainer Azure App Service enligt beskrivningen i Skapa din första funktion som finns på Linux. Basavbildningar som stöds för Azure Functions finns på lagringsplatsen Azure Functions basavbildningar.

I den här guiden får du lära dig att:

  • Skapa en funktionsapp och Dockerfile med hjälp av Azure Functions Core Tools.
  • skapa en anpassad avbildning med Docker
  • Publicera en anpassad avbildning till ett containerregister.
  • Skapa stödresurser i Azure för funktionsappen
  • distribuera en funktionsapp från Docker Hub
  • lägga till programinställningar i funktionsappen.
  • Aktivera kontinuerlig distribution.
  • Aktivera SSH-anslutningar till containern.
  • Lägg till en Queue Storage-utdatabindning.
  • Skapa en funktionsapp och Dockerfile med hjälp av Azure Functions Core Tools.
  • skapa en anpassad avbildning med Docker
  • Publicera en anpassad avbildning till ett containerregister.
  • Skapa stödresurser i Azure för funktionsappen
  • distribuera en funktionsapp från Docker Hub
  • lägga till programinställningar i funktionsappen.
  • Aktivera kontinuerlig distribution.
  • Aktivera SSH-anslutningar till containern.

Du kan följa den här självstudiekursen på valfri dator Windows, macOS eller Linux.

Konfigurera din lokala miljö

Innan du börjar måste du ha följande:

  • Node.jsversionerna Active LTS och Maintenance LTS (8.11.1 och 10.14.1 rekommenderas).

Skapa och aktivera en virtuell miljö

I en lämplig mapp kör du följande kommandon för att skapa och aktivera en virtuell miljö med namnet .venv . Se till att använda python 3,8, 3,7 eller 3,6, som stöds av Azure Functions.

python -m venv .venv
source .venv/bin/activate

Om python inte installerade venv-paketet på din Linux-distribution kör du följande kommando:

sudo apt-get install python3-venv

Du kör alla efterföljande kommandon i den här aktiverade virtuella miljön.

Skapa och testa det lokala funktionsprojekt

Kör följande kommando för det valda språket i en terminal eller kommandotolk för att skapa ett funktionsappsprojekt i en mapp med namnet LocalFunctionsProject .

func init LocalFunctionsProject --worker-runtime dotnet --docker
func init LocalFunctionsProject --worker-runtime node --language javascript --docker
func init LocalFunctionsProject --worker-runtime powershell --docker
func init LocalFunctionsProject --worker-runtime python --docker
func init LocalFunctionsProject --worker-runtime node --language typescript --docker

Kör följande kommando i en tom mapp för att skapa ett funktionsprojekt utifrån en Maven-arketyp.

mvn archetype:generate -DarchetypeGroupId=com.microsoft.azure -DarchetypeArtifactId=azure-functions-archetype -DjavaVersion=8 -Ddocker

Parametern -DjavaVersion talar om för Functions körning vilken version av Java som ska användas. Använd -DjavaVersion=11 om du vill att funktionerna ska köras på Java 11. När du inte anger -DjavaVersion får Maven java 8 som standard. Mer information finns i Java-versioner.

Viktigt

JAVA_HOMEMiljövariabeln måste anges till installationsplatsen för rätt version av JDK för att slutföra den här artikeln.

Maven ber dig om de värden som behövs för att slutföra genereringen av projektet vid distributionen.
Ange följande värden när du tillfrågas:

Prompt Värde Beskrivning
groupId com.fabrikam Ett värde som unikt identifierar projektet i alla projekt och som följer namngivningsreglerna för Java.
artifactId fabrikam-functions Ett värde som är namnet på jar-numret, utan versionsnummer.
Version 1.0-SNAPSHOT Välj standardvärdet.
Paket com.fabrikam.functions Ett värde som är Java-paketet för den genererade funktionskoden. Använd standardvärdet.

Skriv Y eller tryck på Retur för att bekräfta.

Maven skapar projektfilerna i en ny mapp med namnet artifactId, som i det här exemplet är fabrikam-functions .

func init LocalFunctionsProject --worker-runtime custom --docker

Alternativet genererar en för projektet, som definierar en lämplig anpassad --docker container för användning med Azure Functions och den valda Dockerfile körningen.

Navigera till projektmappen:

cd LocalFunctionsProject
cd fabrikam-functions

Lägg till en funktion i projektet med hjälp av följande kommando, där argumentet är det unika namnet på funktionen och --name --template argumentet anger funktionens utlösare. func new skapar en undermapp som matchar funktionsnamnet som innehåller en kodfil som är lämplig för projektets valda språk och en konfigurationsfil med namnetfunction.jspå.

func new --name HttpExample --template "HTTP trigger"

Lägg till en funktion i projektet med hjälp av följande kommando, där argumentet är det unika namnet på funktionen och --name --template argumentet anger funktionens utlösare. func new skapar en undermapp som matchar funktionsnamnet som innehåller en konfigurationsfil med namnetfunction.jspå.

func new --name HttpExample --template "HTTP trigger"

Skapa en fil i projektmappen med namnet handler i en textredigerare. R. Lägg till följande som dess innehåll.

library(httpuv)

PORTEnv <- Sys.getenv("FUNCTIONS_CUSTOMHANDLER_PORT")
PORT <- strtoi(PORTEnv , base = 0L)

http_not_found <- list(
  status=404,
  body='404 Not Found'
)

http_method_not_allowed <- list(
  status=405,
  body='405 Method Not Allowed'
)

hello_handler <- list(
  GET = function (request) {
    list(body=paste(
      "Hello,",
      if(substr(request$QUERY_STRING,1,6)=="?name=") 
        substr(request$QUERY_STRING,7,40) else "World",
      sep=" "))
  }
)

routes <- list(
  '/api/HttpExample' = hello_handler
)

router <- function (routes, request) {
  if (!request$PATH_INFO %in% names(routes)) {
    return(http_not_found)
  }
  path_handler <- routes[[request$PATH_INFO]]

  if (!request$REQUEST_METHOD %in% names(path_handler)) {
    return(http_method_not_allowed)
  }
  method_handler <- path_handler[[request$REQUEST_METHOD]]

  return(method_handler(request))
}

app <- list(
  call = function (request) {
    response <- router(routes, request)
    if (!'status' %in% names(response)) {
      response$status <- 200
    }
    if (!'headers' %in% names(response)) {
      response$headers <- list()
    }
    if (!'Content-Type' %in% names(response$headers)) {
      response$headers[['Content-Type']] <- 'text/plain'
    }

    return(response)
  }
)

cat(paste0("Server listening on :", PORT, "...\n"))
runServer("0.0.0.0", PORT, app)

I host.jspå ändrar du avsnittet för att konfigurera den anpassade customHandler hanterarens startkommando.

"customHandler": {
  "description": {
      "defaultExecutablePath": "Rscript",
      "arguments": [
      "handler.R"
    ]
  },
  "enableForwardingHttpRequest": true
}

Om du vill testa funktionen lokalt startar du den lokala Azure Functions-körningsvärden i projektmappens rot:

func start  
func start  
npm install
npm start
mvn clean package  
mvn azure-functions:run
R -e "install.packages('httpuv', repos='http://cran.rstudio.com/')"
func start

När du ser HttpExample slutpunkten i utdata navigerar du till http://localhost:7071/api/HttpExample?name=Functions . Webbläsaren bör visa ett "hello"-meddelande som returnerar Functions , värdet som angetts till name frågeparametern.

Använd Ctrl - C för att stoppa värden.

Skapa containeravbildningen och testa lokalt

(Valfritt) Granska Dockerfile i projektmappens rot. Dockerfile beskriver den miljö som krävs för att köra funktionsappen på Linux. Den fullständiga listan över basavbildningar som Azure Functions finns på Azure Functions basavbildningssidan.

Granska Dockerfile i projektmappens rot. Dockerfile beskriver den miljö som krävs för att köra funktionsappen på Linux. Anpassade hanterarprogram använder mcr.microsoft.com/azure-functions/dotnet:3.0-appservice avbildningen som bas.

Ändra Dockerfile för att installera R. Ersätt innehållet i Dockerfile med följande.

FROM mcr.microsoft.com/azure-functions/dotnet:3.0-appservice 
ENV AzureWebJobsScriptRoot=/home/site/wwwroot \
    AzureFunctionsJobHost__Logging__Console__IsEnabled=true

RUN apt update && \
    apt install -y r-base && \
    R -e "install.packages('httpuv', repos='http://cran.rstudio.com/')"

COPY . /home/site/wwwroot

I rotprojektmappen kör du kommandot docker build och anger ett namn, azurefunctionsimage , och tagg, v1.0.0 . Ersätt <DOCKER_ID> med ditt konto-ID för Docker Hub. Det här kommandot skapar Docker-avbildningen för containern.

docker build --tag <DOCKER_ID>/azurefunctionsimage:v1.0.0 .

När kommandot har slutförts kan du köra den nya containern lokalt.

Om du vill testa bygget kör du avbildningen i en lokal container med kommandot docker run, ersätter igen med ditt Docker-ID och lägger till <DOCKER_ID ports-argumentet, -p 8080:80 :

docker run -p 8080:80 -it <docker_id>/azurefunctionsimage:v1.0.0

När avbildningen körs i en lokal container öppnar du en webbläsare till http://localhost:8080 , som ska visa platshållarbilden som visas nedan. Avbildningen visas nu eftersom funktionen körs i den lokala containern, precis som i Azure, vilket innebär att den skyddas av en åtkomstnyckel enligt definitionen i function.jspå med "authLevel": "function" egenskapen . Containern har ännu inte publicerats till en funktionsapp i Azure, så nyckeln är inte tillgänglig ännu. Om du vill testa mot den lokala containern stoppar du Docker, ändrar auktoriseringsegenskapen till , återskapar "authLevel": "anonymous" avbildningen och startar om Docker. Återställ sedan "authLevel": "function" ifunction.jspå. Mer information finns i auktoriseringsnycklar.

Platshållarbild som anger att containern körs lokalt

När avbildningen körs i en lokal container bläddrar du till http://localhost:8080/api/HttpExample?name=Functions , som ska visa samma "hello"-meddelande som tidigare. Eftersom Maven-arketypen genererar en HTTP-utlöst funktion som använder anonym auktorisering kan du fortfarande anropa funktionen även om den körs i containern.

När du har verifierat funktionsappen i containern stoppar du Docker med Ctrl + C.

Push-skicka avbildningen till Docker Hub

Docker Hub är ett containerregister som är värd för avbildningar och tillhandahåller avbildnings- och containertjänster. Om du vill dela avbildningen, vilket innefattar distribution till Azure, måste du push-installera den i ett register.

  1. Om du inte redan har loggat in på Docker gör du det med kommandot docker login och ersätter <docker_id> med ditt Docker-ID. Det här kommandot uppmanar dig att ange ditt användarnamn och lösenord. Ett meddelande om att inloggningen lyckades bekräftar att du är inloggad.

    docker login
    
  2. När du har loggat in kan du push-skicka avbildningen till Docker Hub med kommandot docker push och återigen ersätta <docker_id> med ditt Docker-ID.

    docker push <docker_id>/azurefunctionsimage:v1.0.0
    
  3. Beroende på nätverkets hastighet kan det ta några minuter att push-pusha avbildningen första gången (det går mycket snabbare att push-pusha efterföljande ändringar). Medan du väntar kan du gå vidare till nästa avsnitt och skapa Azure-resurser i en annan terminal.

Skapa azure-stödresurser för din funktion

Om du vill distribuera funktionskoden till Azure måste du skapa tre resurser:

  • En resursgrupp, som är en logisk container för relaterade resurser.
  • Ett Azure Storage-konto som upprätthåller tillstånd och annan information om dina projekt.
  • En funktionsapp som tillhandahåller miljön för att köra funktionskoden. En funktionsapp mappar till ditt lokala funktionsprojekt och gör att du kan gruppera funktioner som en logisk enhet för enklare hantering, distribution och delning av resurser.

Du använder Azure CLI-kommandon för att skapa dessa objekt. Varje kommando ger JSON-utdata när de har slutförts.

  1. Logga in på Azure med kommandot az login:

    az login
    
  2. Skapa en resursgrupp med kommandot az group create. I följande exempel skapas en resursgrupp med AzureFunctionsContainers-rg namnet i westeurope regionen . (Du skapar vanligtvis din resursgrupp och dina resurser i en region nära dig med hjälp av en tillgänglig region från az account list-locations kommandot .)

    az group create --name AzureFunctionsContainers-rg --location westeurope
    

    Anteckning

    Du kan inte vara värd för Linux Windows appar i samma resursgrupp. Om du har en befintlig resursgrupp med namnet Windows en funktionsapp eller AzureFunctionsContainers-rg webbapp måste du använda en annan resursgrupp.

  3. Skapa ett allmänt lagringskonto i resursgruppen och regionen med hjälp av kommandot az storage account create. I följande exempel ersätter du <storage_name> med ett globalt unikt namn som passar dig. Namn får endast innehålla tre till 24 tecken och gemener. Standard_LRS anger ett vanligt konto för generell användning.

    az storage account create --name <storage_name> --location westeurope --resource-group AzureFunctionsContainers-rg --sku Standard_LRS
    

    Lagringskontot ådrar sig bara några cent för den här självstudien.

  4. Använd kommandot för att skapa en Premium-plan för Azure Functions med namnet i prisnivån Elastic Premium 1 ( ), i regionen Europa, västra ( , eller använd en lämplig region nära dig) och i en myPremiumPlan --sku EP1 -location westeurope Linux-container ( --is-linux ).

    az functionapp plan create --resource-group AzureFunctionsContainers-rg --name myPremiumPlan --location westeurope --number-of-workers 1 --sku EP1 --is-linux
    

    Vi använder Premium här, som kan skalas efter behov. Mer information om värdfunktioner finns i Azure Functions hosting plans comparison (Jämförelse av Azure Functions-värdplaner). Om du vill beräkna kostnader kan du gå till prissättningssidan för Functions.

    Kommandot innehåller också en associerad Azure Application Insights-instans i samma resursgrupp, med vilken du kan övervaka funktionsappen och visa loggar. Mer information finns i Övervaka Azure Functions. Instansen medför inga kostnader förrän du aktiverar den.

Skapa och konfigurera en funktionsapp i Azure med avbildningen

En funktionsapp i Azure hanterar körningen av dina funktioner i din värdplan. I det här avsnittet använder du Azure-resurserna från föregående avsnitt för att skapa en funktionsapp från en avbildning på Docker Hub och konfigurera den med en anslutningssträng som ska Azure Storage.

  1. Skapa Functions-appen med kommandot az functionapp create. I följande exempel ersätter du <storage_name> med namnet som du använde i föregående avsnitt för lagringskontot. Ersätt även <app_name> med ett globalt unikt namn som är lämpligt för dig och med ditt <docker_id> Docker-ID.

    az functionapp create --name <app_name> --storage-account <storage_name> --resource-group AzureFunctionsContainers-rg --plan myPremiumPlan --runtime <functions runtime stack> --deployment-container-image-name <docker_id>/azurefunctionsimage:v1.0.0
    
    az functionapp create --name <app_name> --storage-account <storage_name> --resource-group AzureFunctionsContainers-rg --plan myPremiumPlan --runtime custom --deployment-container-image-name <docker_id>/azurefunctionsimage:v1.0.0
    

    Parametern deployment-container-image-name anger vilken avbildning som ska användas för funktionsappen. Du kan använda kommandot az functionapp config container show för att visa information om avbildningen som används för distribution. Du kan också använda kommandot az functionapp config container set för att distribuera från en annan avbildning.

    Tips

    Du kan använda inställningen DisableColor i filen host.jsför att förhindra att ANSI-kontrolltecken skrivs till containerloggarna.

  2. Visa anslutningssträngen för lagringskontot som du skapade med kommandot az storage account show-connection-string. Ersätt <storage-name> med namnet på lagringskontot som du skapade ovan:

    az storage account show-connection-string --resource-group AzureFunctionsContainers-rg --name <storage_name> --query connectionString --output tsv
    
  3. Lägg till den här inställningen i funktionsappen med kommandot az functionapp config appsettings set. I följande kommando ersätter du med namnet på funktionsappen och ersätter med anslutningssträngen från föregående steg (en lång kodad sträng som börjar med <app_name> <connection_string> "DefaultEndpointProtocol="):

    az functionapp config appsettings set --name <app_name> --resource-group AzureFunctionsContainers-rg --settings AzureWebJobsStorage=<connection_string>
    

    Tips

    I Bash kan du använda en gränssnittsvariabel för att avbilda anslutningssträngen i stället för att använda Urklipp. Använd först följande kommando för att skapa en variabel med anslutningssträngen:

    storageConnectionString=$(az storage account show-connection-string --resource-group AzureFunctionsContainers-rg --name <storage_name> --query connectionString --output tsv)
    

    Se sedan variabeln i det andra kommandot:

    az functionapp config appsettings set --name <app_name> --resource-group AzureFunctionsContainers-rg --settings AzureWebJobsStorage=$storageConnectionString
    
  4. Funktionen kan nu använda den här anslutningssträngen för att komma åt lagringskontot.

Anteckning

Om du publicerar din anpassade avbildning till ett privat containerkonto bör du använda miljövariabler i Dockerfile för anslutningssträngen i stället. Mer information finns i ENV-instruktionen. Du bör också ange variablerna DOCKER_REGISTRY_SERVER_USERNAME och DOCKER_REGISTRY_SERVER_PASSWORD . Om du vill använda värdena måste du återskapa avbildningen, push-skicka avbildningen till registret och sedan starta om funktionsappen i Azure.

Verifiera dina funktioner i Azure

När avbildningen har distribuerats till funktionsappen i Azure kan du nu anropa funktionen via HTTP-begäranden. Eftersom function.jspå-definitionen innehåller egenskapen måste du först hämta åtkomstnyckeln (kallas även "funktionsnyckeln") och inkludera den som en URL-parameter i alla förfrågningar till "authLevel": "function" slutpunkten.

  1. Hämta funktions-URL:en med åtkomstnyckeln (funktion) med hjälp av Azure Portal eller med hjälp av Azure CLI med az rest kommandot .)

    1. Logga in på Azure Portal och sök sedan efter och välj Funktionsapp.

    2. Välj den funktion som du vill verifiera.

    3. I det vänstra navigeringsfönstret väljer du Funktioner och sedan den funktion som du vill verifiera.

      Välj din funktion i Azure Portal

    4. Välj Hämta funktions-URL.

      Hämta funktions-URL:en från Azure Portal

    5. I popup-fönstret väljer du standard (funktionsnyckel) och kopierar sedan URL:en till Urklipp. Nyckeln är strängen med tecken som följer ?code= .

      Välj standardåtkomstnyckeln för funktionen

    Anteckning

    Eftersom funktionsappen distribueras som en container kan du inte göra ändringar i funktionskoden i portalen. Du måste i stället uppdatera projektet i den lokala avbildningen, skicka avbildningen till registret igen och sedan distribuera om till Azure. Du kan konfigurera kontinuerlig distribution i ett senare avsnitt.

  2. Klistra in funktions-URL:en i webbläsarens adressfält och lägg till &name=Azure parametern i slutet av url:en. Text som "Hello, Azure" bör visas i webbläsaren.

    Funktionssvar i webbläsaren.

  3. Om du vill testa auktoriseringen tar du bort parametern från code= URL:en och kontrollerar att du inte får något svar från funktionen.

Aktivera kontinuerlig distribution till Azure

Du kan aktivera Azure Functions att automatiskt uppdatera distributionen av en avbildning när du uppdaterar avbildningen i registret.

  1. Aktivera kontinuerlig distribution med kommandot az functionapp deployment container config och ersätt <app_name> med namnet på funktionsappen:

    az functionapp deployment container config --enable-cd --query CI_CD_URL --output tsv --name <app_name> --resource-group AzureFunctionsContainers-rg
    

    Det här kommandot aktiverar kontinuerlig distribution och returnerar url:en för distributionswebhooken. (Du kan hämta den här URL:en när som helst senare med hjälp av kommandot az functionapp deployment container show-cd-url.)

  2. Kopiera url:en för distributionswebhooken till Urklipp.

  3. Öppna Docker Hub,logga in och välj Lagringsplatsen i navigeringsfältet. Leta upp och välj bild, välj fliken Webhooks, ange ett Webhook-namn, klistra in url:en i Webhook-URL:en och välj sedan Skapa:

    Lägga till webhooken i dockerHub-lagringsplatsen

  4. När webhooken är inställd Azure Functions distribuerar om avbildningen när du uppdaterar den i Docker Hub.

Aktivera SSH-anslutningar

SSH möjliggör säker kommunikation mellan en container och en klient. Med SSH aktiverat kan du ansluta till din container med hjälp App Service Avancerade verktyg (Kudu). För att göra det enkelt att ansluta till din container med hjälp av SSH Azure Functions en basavbildning som redan har SSH aktiverat. Du behöver bara redigera din Dockerfile och sedan återskapa och distribuera om avbildningen. Du kan sedan ansluta till containern via Avancerade verktyg (Kudu)

  1. I din Dockerfile lägger du till strängen -appservice i basavbildningen i FROM instruktionen:

    FROM mcr.microsoft.com/azure-functions/dotnet:3.0-appservice
    
    FROM mcr.microsoft.com/azure-functions/node:2.0-appservice
    
    FROM mcr.microsoft.com/azure-functions/powershell:2.0-appservice
    
    FROM mcr.microsoft.com/azure-functions/python:2.0-python3.7-appservice
    
    FROM mcr.microsoft.com/azure-functions/node:2.0-appservice
    
  2. Återskapa avbildningen med kommandot docker build igen och ersätt med ditt <docker_id> Docker-ID:

    docker build --tag <docker_id>/azurefunctionsimage:v1.0.0 .
    
  3. Push-överför den uppdaterade avbildningen till Docker Hub, vilket bör ta betydligt kortare tid än den första push-överföringen att bara de uppdaterade segmenten i avbildningen behöver laddas upp.

    docker push <docker_id>/azurefunctionsimage:v1.0.0
    
  4. Azure Functions automatiskt om avbildningen till din functions-app; processen sker på mindre än en minut.

  5. Öppna i en webbläsare https://<app_name>.scm.azurewebsites.net/ och ersätt med ditt unika <app_name> namn. Den här URL:en är kudu-slutpunkten (Advanced Tools) för din funktionsappcontainer.

  6. Logga in på ditt Azure-konto och välj sedan SSH för att upprätta en anslutning till containern. Det kan ta en stund att ansluta om Azure fortfarande uppdaterar containeravbildningen.

  7. När en anslutning har upprättats med containern kör du kommandot top för att visa de processer som körs.

    Linux-toppkommando som körs i en SSH-session

Skriva till en Azure Storage kö

Azure Functions kan du ansluta dina funktioner till andra Azure-tjänster och -resurser utan att behöva skriva din egen integreringskod. Dessa bindningar , som representerar både indata och utdata, deklareras i funktionsdefinitionen. Data från bindningar skickas som parametrar till funktionen. En utlösare är en särskild typ av indatabindning. Även om en funktion bara har en utlösare kan den ha flera indata- och utdatabindningar. Mer information finns i Azure Functions utlösare och bindningar.

Det här avsnittet visar hur du integrerar din funktion med en Azure Storage kö. Den utdatabindning som du lägger till i den här funktionen skriver data från en HTTP-begäran till ett meddelande i kön.

Hämta Azure Storage anslutnings sträng

Tidigare skapade du ett Azure Storage-konto som ska användas av Function-appen. Anslutnings strängen för det här kontot lagras på ett säkert sätt i appinställningar i Azure. Genom att Hämta inställningen till local.settings.jsi filen kan du använda den för att skriva till en lagrings kö i samma konto när funktionen körs lokalt.

  1. Kör följande kommando från roten i projektet och Ersätt <app_name> med namnet på din Function-app från föregående snabb start. Det här kommandot skriver över alla befintliga värden i filen.

    func azure functionapp fetch-app-settings <app_name>
    
  2. Öppna local.settings.jspå och leta upp värdet med namnet AzureWebJobsStorage , som är anslutnings strängen för lagrings kontot. Du använder namnet AzureWebJobsStorage och anslutnings strängen i andra avsnitt i den här artikeln.

Viktigt

Eftersom local.settings.jspå innehåller hemligheter som hämtats från Azure ska du alltid utesluta den här filen från käll kontroll. Filen . gitignore som skapas med ett lokalt Functions-projekt utesluter filen som standard.

Registrera bindningstillägg

Med undantag för HTTP-och timer-utlösare implementeras bindningar som tilläggs paket. Kör följande dotNet Lägg till paket kommando i terminalfönstret för att lägga till lagrings tilläggs paketet i projektet.

dotnet add package Microsoft.Azure.WebJobs.Extensions.Storage --version 3.0.4

Nu kan du lägga till bindningen för Storage-utdata i projektet.

Lägg till en definition för utgående bindning i funktionen

Även om en funktion bara kan ha en utlösare, kan den ha flera indata-och utgående bindningar, vilket gör att du kan ansluta till andra Azure-tjänster och-resurser utan att skriva anpassad integrerings kod.

Du deklarerar dessa bindningar i function.js filen i mappen function. I den tidigare snabb starten innehåller function.js filen i HttpExample -mappen två bindningar i bindings samlingen:

"bindings": [
    {
        "authLevel": "function",
        "type": "httpTrigger",
        "direction": "in",
        "name": "req",
        "methods": [
            "get",
            "post"
        ]
    },
    {
        "type": "http",
        "direction": "out",
        "name": "res"
    }
]
"scriptFile": "__init__.py",
"bindings": [
    {
        "authLevel": "function",
        "type": "httpTrigger",
        "direction": "in",
        "name": "req",
        "methods": [
            "get",
            "post"
        ]
    },
    {
        "type": "http",
        "direction": "out",
        "name": "$return"
    }
"bindings": [
  {
    "authLevel": "function",
    "type": "httpTrigger",
    "direction": "in",
    "name": "Request",
    "methods": [
      "get",
      "post"
    ]
  },
  {
    "type": "http",
    "direction": "out",
    "name": "Response"
  }
]

Varje bindning har minst en typ, en riktning och ett namn. I exemplet ovan är den första bindningen av typen httpTrigger med riktningen in . I in riktningen anger du name namnet på en indataparameter som skickas till funktionen när den anropas av utlösaren.

Den andra bindningen i samlingen heter res . Den här http bindningen är en utgående bindning ( out ) som används för att skriva http-svaret.

Om du vill skriva till en Azure Storage kö från den här funktionen lägger du till en out bindning av typen queue med namnet msg , som du ser i koden nedan:

    {
      "authLevel": "function",
      "type": "httpTrigger",
      "direction": "in",
      "name": "req",
      "methods": [
        "get",
        "post"
      ]
    },
    {
      "type": "http",
      "direction": "out",
      "name": "res"
    },
    {
      "type": "queue",
      "direction": "out",
      "name": "msg",
      "queueName": "outqueue",
      "connection": "AzureWebJobsStorage"
    }
  ]
}

Den andra bindningen i samlingen är av typen http med riktningen out , i så fall är den särskilda name av $return anger att den här bindningen använder funktionens retur värde istället för att ange en indataparameter.

Om du vill skriva till en Azure Storage kö från den här funktionen lägger du till en out bindning av typen queue med namnet msg , som du ser i koden nedan:

"bindings": [
  {
    "authLevel": "anonymous",
    "type": "httpTrigger",
    "direction": "in",
    "name": "req",
    "methods": [
      "get",
      "post"
    ]
  },
  {
    "type": "http",
    "direction": "out",
    "name": "$return"
  },
  {
    "type": "queue",
    "direction": "out",
    "name": "msg",
    "queueName": "outqueue",
    "connection": "AzureWebJobsStorage"
  }
]

Den andra bindningen i samlingen heter res . Den här http bindningen är en utgående bindning ( out ) som används för att skriva http-svaret.

Om du vill skriva till en Azure Storage kö från den här funktionen lägger du till en out bindning av typen queue med namnet msg , som du ser i koden nedan:

    {
      "authLevel": "function",
      "type": "httpTrigger",
      "direction": "in",
      "name": "Request",
      "methods": [
        "get",
        "post"
      ]
    },
    {
      "type": "http",
      "direction": "out",
      "name": "Response"
    },
    {
      "type": "queue",
      "direction": "out",
      "name": "msg",
      "queueName": "outqueue",
      "connection": "AzureWebJobsStorage"
    }
  ]
}

I det här fallet msg anges funktionen som ett argument för utdata. För en queue typ måste du också ange namnet på kön i queueName och ange namnet på den Azure Storage anslutningen (från local.settings.jspå) i connection .

I ett C#-klass biblioteks projekt definieras bindningarna som binding-attribut i funktions metoden. Den function.js filen som krävs av Functions genereras sedan automatiskt baserat på dessa attribut.

Öppna projekt filen HttpExample. cs och Lägg till följande parameter i Run metod definitionen:

[Queue("outqueue"),StorageAccount("AzureWebJobsStorage")] ICollector<string> msg,

msgParametern är en ICollector<T> typ som representerar en samling meddelanden som skrivs till en utgående bindning när funktionen slutförs. I det här fallet är utdata en lagrings kö med namnet outqueue . Anslutnings strängen för lagrings kontot anges av StorageAccountAttribute . Det här attributet anger den inställning som innehåller lagrings kontots anslutnings sträng och kan tillämpas på klass-, metod-eller parameter nivå. I det här fallet kan du utelämna StorageAccountAttribute eftersom du redan använder standard lagrings kontot.

Definitionen av Run-metoden bör nu se ut så här:

[FunctionName("HttpExample")]
public static async Task<IActionResult> Run(
    [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req, 
    [Queue("outqueue"),StorageAccount("AzureWebJobsStorage")] ICollector<string> msg, 
    ILogger log)

I ett Java-projekt definieras bindningarna som bindnings anteckningar i funktions metoden. function.js filen skapas sedan automatiskt baserat på dessa anteckningar.

Bläddra till platsen för funktions koden under src/main/Java, öppna filen Function. java -projekt och Lägg till följande parameter i run metod definitionen:

@QueueOutput(name = "msg", queueName = "outqueue", connection = "AzureWebJobsStorage") OutputBinding<String> msg

msgParametern är en OutputBinding<T> typ som representerar en samling strängar som skrivs som meddelanden till en utgående bindning när funktionen slutförs. I det här fallet är utdata en lagrings kö med namnet outqueue . Anslutnings strängen för lagrings kontot anges av- connection metoden. I stället för själva anslutnings strängen skickar du den program inställning som innehåller anslutnings strängen för lagrings kontot.

runMetod definitionen bör nu se ut som i följande exempel:

@FunctionName("HttpTrigger-Java")
public HttpResponseMessage run(
        @HttpTrigger(name = "req", methods = {HttpMethod.GET, HttpMethod.POST}, authLevel = AuthorizationLevel.FUNCTION)  
        HttpRequestMessage<Optional<String>> request, 
        @QueueOutput(name = "msg", queueName = "outqueue", connection = "AzureWebJobsStorage") 
        OutputBinding<String> msg, final ExecutionContext context) {
    ...
}

Lägga till kod för att använda utdatabindningen

När köbindningen har definierats kan du uppdatera funktionen så att den tar emot msg utdataparametern och skriver meddelanden till kön.

Uppdatera HttpExample \ _ _ init _ _ . py för att matcha följande kod, genom att lägga till msg parametern i funktions definitionen och msg.set(name) under if name: instruktionen.

import logging

import azure.functions as func


def main(req: func.HttpRequest, msg: func.Out[func.QueueMessage]) -> str:

    name = req.params.get('name')
    if not name:
        try:
            req_body = req.get_json()
        except ValueError:
            pass
        else:
            name = req_body.get('name')

    if name:
        msg.set(name)
        return func.HttpResponse(f"Hello {name}!")
    else:
        return func.HttpResponse(
            "Please pass a name on the query string or in the request body",
            status_code=400
        )

msgParametern är en instans av azure.functions.InputStream class . setMetoden skriver ett sträng meddelande till kön, i det här fallet skickas namnet till funktionen i URL-frågesträngen.

Lägg till kod som använder msg objektet utgående bindning på context.bindings för att skapa ett köat meddelande. Lägg till den här koden före context.res instruktionen.

// Add a message to the Storage queue,
// which is the name passed to the function.
context.bindings.msg = (req.query.name || req.body.name);

I det här läget bör din funktion se ut så här:

module.exports = async function (context, req) {
    context.log('JavaScript HTTP trigger function processed a request.');

    if (req.query.name || (req.body && req.body.name)) {
        // Add a message to the Storage queue,
        // which is the name passed to the function.
        context.bindings.msg = (req.query.name || req.body.name);
        context.res = {
            // status: 200, /* Defaults to 200 */
            body: "Hello " + (req.query.name || req.body.name)
        };
    }
    else {
        context.res = {
            status: 400,
            body: "Please pass a name on the query string or in the request body"
        };
    }
};

Lägg till kod som använder msg objektet utgående bindning på context.bindings för att skapa ett köat meddelande. Lägg till den här koden före context.res instruktionen.

context.bindings.msg = name;

I det här läget bör din funktion se ut så här:

import { AzureFunction, Context, HttpRequest } from "@azure/functions"

const httpTrigger: AzureFunction = async function (context: Context, req: HttpRequest): Promise<void> {
    context.log('HTTP trigger function processed a request.');
    const name = (req.query.name || (req.body && req.body.name));

    if (name) {
        // Add a message to the storage queue, 
        // which is the name passed to the function.
        context.bindings.msg = name; 
        // Send a "hello" response.
        context.res = {
            // status: 200, /* Defaults to 200 */
            body: "Hello " + (req.query.name || req.body.name)
        };
    }
    else {
        context.res = {
            status: 400,
            body: "Please pass a name on the query string or in the request body"
        };
    }
};

export default httpTrigger;

Lägg till kod som använder Push-OutputBinding cmdleten för att skriva text till kön med hjälp av msg utgående bindning. Lägg till den här koden innan du anger statusen OK i if instruktionen.

$outputMsg = $name
Push-OutputBinding -name msg -Value $outputMsg

I det här läget bör din funktion se ut så här:

using namespace System.Net

# Input bindings are passed in via param block.
param($Request, $TriggerMetadata)

# Write to the Azure Functions log stream.
Write-Host "PowerShell HTTP trigger function processed a request."

# Interact with query parameters or the body of the request.
$name = $Request.Query.Name
if (-not $name) {
    $name = $Request.Body.Name
}

if ($name) {
    # Write the $name value to the queue, 
    # which is the name passed to the function.
    $outputMsg = $name
    Push-OutputBinding -name msg -Value $outputMsg

    $status = [HttpStatusCode]::OK
    $body = "Hello $name"
}
else {
    $status = [HttpStatusCode]::BadRequest
    $body = "Please pass a name on the query string or in the request body."
}

# Associate values to output bindings by calling 'Push-OutputBinding'.
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
    StatusCode = $status
    Body = $body
})

Lägg till kod som använder msg objektet utgående bindning för att skapa ett Queue-meddelande. Lägg till den här koden innan metoden returnerar.

if (!string.IsNullOrEmpty(name))
{
    // Add a message to the output collection.
    msg.Add(string.Format("Name passed to the function: {0}", name));
}

I det här läget bör din funktion se ut så här:

[FunctionName("HttpExample")]
public static async Task<IActionResult> Run(
    [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req, 
    [Queue("outqueue"),StorageAccount("AzureWebJobsStorage")] ICollector<string> msg, 
    ILogger log)
{
    log.LogInformation("C# HTTP trigger function processed a request.");

    string name = req.Query["name"];

    string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
    dynamic data = JsonConvert.DeserializeObject(requestBody);
    name = name ?? data?.name;

    if (!string.IsNullOrEmpty(name))
    {
        // Add a message to the output collection.
        msg.Add(string.Format("Name passed to the function: {0}", name));
    }
    return name != null
        ? (ActionResult)new OkObjectResult($"Hello, {name}")
        : new BadRequestObjectResult("Please pass a name on the query string or in the request body");
}

Nu kan du använda den nya msg parametern för att skriva till utgående bindning från din funktions kod. Lägg till följande kodrad innan du lyckas med att lägga till värdet för name i msg utmatnings bindningen.

msg.setValue(name);

När du använder en utgående bindning behöver du inte använda Azure Storage SDK-koden för autentisering, hämta en referens till kön eller skriva data. Bindningarna Functions Runtime och Queue output utför dessa uppgifter åt dig.

runMetoden bör nu se ut som i följande exempel:

public HttpResponseMessage run(
        @HttpTrigger(name = "req", methods = {HttpMethod.GET, HttpMethod.POST}, authLevel = AuthorizationLevel.ANONYMOUS) 
        HttpRequestMessage<Optional<String>> request, 
        @QueueOutput(name = "msg", queueName = "outqueue", 
        connection = "AzureWebJobsStorage") OutputBinding<String> msg, 
        final ExecutionContext context) {
    context.getLogger().info("Java HTTP trigger processed a request.");

    // Parse query parameter
    String query = request.getQueryParameters().get("name");
    String name = request.getBody().orElse(query);

    if (name == null) {
        return request.createResponseBuilder(HttpStatus.BAD_REQUEST)
        .body("Please pass a name on the query string or in the request body").build();
    } else {
        // Write the name to the message queue. 
        msg.setValue(name);

        return request.createResponseBuilder(HttpStatus.OK).body("Hello, " + name).build();
    }
}

Uppdatera testerna

Eftersom archetype också skapar en uppsättning tester måste du uppdatera de här testerna för att hantera den nya msg parametern i run Metodsignaturen.

Bläddra till platsen för test koden under src/test/java, öppna filen Function. java -projekt och ersätt kodraden under //Invoke med följande kod.

@SuppressWarnings("unchecked")
final OutputBinding<String> msg = (OutputBinding<String>)mock(OutputBinding.class);
final HttpResponseMessage ret = new Function().run(req, msg, context);

Uppdatera avbildningen i registret

  1. I rotmappen kör du docker build igen och uppdaterar den här gången versionen i taggen till v1.0.1 . Som tidigare ersätter du <docker_id> med ditt Docker Hub-ID:

    docker build --tag <docker_id>/azurefunctionsimage:v1.0.1 .
    
  2. Skicka tillbaka den uppdaterade avbildningen till lagringsplatsen med docker push :

    docker push <docker_id>/azurefunctionsimage:v1.0.1
    
  3. Eftersom du har konfigurerat kontinuerlig leverans uppdaterar automatiskt uppdatering av avbildningen i registret automatiskt funktionsappen i Azure.

Visa meddelandet i Azure Storage kön

I en webbläsare använder du samma URL som tidigare för att anropa funktionen. Webbläsaren bör visa samma svar som tidigare, eftersom du inte har modifierat den delen av funktionskoden. Den tillagda koden skrev dock ett meddelande med name URL-parametern till outqueue lagringskön.

Du kan visa kön i Azure Portal eller i Microsoft Azure Storage Explorer. Du kan också visa kön i Azure CLI enligt beskrivningen i följande steg:

  1. Öppna funktionsprojektets namnlocal.setting.js filen och kopiera värdet för anslutningssträngen. Kör följande kommando i en terminal eller ett kommandofönster för att skapa en miljövariabel med namnet och klistra AZURE_STORAGE_CONNECTION_STRING in din specifika anslutningssträng i stället för <MY_CONNECTION_STRING> . (Den här miljövariabeln innebär att du inte behöver ange anslutningssträngen till varje efterföljande kommando med --connection-string argumentet .)

    export AZURE_STORAGE_CONNECTION_STRING="<MY_CONNECTION_STRING>"
    
  2. (Valfritt) Använd kommandot az storage queue list för att visa Storage-köerna i ditt konto. Utdata från det här kommandot ska innehålla en kö med namnet outqueue , som skapades när funktionen skrev sitt första meddelande till kön.

    az storage queue list --output tsv
    
  3. Använd kommandot az storage message get för att läsa meddelandet från den här kön, vilket bör vara det förnamn som du använde när du testade funktionen tidigare. Kommandot läser och tar bort det första meddelandet från kön.

    echo `echo $(az storage message get --queue-name outqueue -o tsv --query '[].{Message:content}') | base64 --decode`
    

    Eftersom meddelandetexten lagras base64-kodadmåste meddelandet avkodas innan det visas. När du az storage message get har kört tas meddelandet bort från kön. Om det bara fanns ett meddelande i hämtar du inte ett meddelande när du kör det här kommandot outqueue en andra gång och får i stället ett fel.

Rensa resurser

Om du vill fortsätta arbeta med Azure Function med hjälp av de resurser som du skapade i den här självstudien kan du lämna alla dessa resurser på plats. Eftersom du har skapat Premium plan Azure Functions kommer du att få en eller två USD per dag i löpande kostnader.

För att undvika löpande kostnader tar du AzureFunctionsContainer-rg bort resursgruppen för att rensa alla resurser i gruppen:

az group delete --name AzureFunctionsContainer-rg

Nästa steg