Anslut Azure Functions att Azure Storage använda kommandoradsverktyg

I den här artikeln integrerar du en Azure Storage med funktionen och lagringskontot som du skapade i föregående snabbstartsartikel. Du uppnår den här integreringen genom att använda en utdatabindning som skriver data från en HTTP-begäran till ett meddelande i kön. När du slutför den här artikeln tillkommer inga ytterligare kostnader utöver de få USD-centen i den föregående snabbstarten. Mer information om bindningar finns i Azure Functions utlösare och bindningar.

Konfigurera din lokala miljö

Innan du börjar måste du slutföra artikeln Snabbstart: Skapa ett Azure Functions-projekt från kommandoraden. Om du redan rensade resurser i slutet av artikeln går du igenom stegen igen för att återskapa funktionsappen och relaterade resurser i Azure.

Innan du börjar måste du slutföra artikeln Snabbstart: Skapa ett Azure Functions-projekt från kommandoraden. Om du redan rensade resurser i slutet av artikeln går du igenom stegen igen för att återskapa funktionsappen och relaterade resurser i Azure.

Innan du börjar måste du slutföra artikeln Snabbstart: Skapa ett Azure Functions-projekt från kommandoraden. Om du redan rensade resurser i slutet av artikeln går du igenom stegen igen för att återskapa funktionsappen och relaterade resurser i Azure.

Innan du börjar måste du slutföra artikeln Snabbstart: Skapa ett Azure Functions-projekt från kommandoraden. Om du redan rensade resurser i slutet av artikeln går du igenom stegen igen för att återskapa funktionsappen och relaterade resurser i Azure.

Innan du börjar måste du slutföra artikeln Snabbstart: Skapa ett Azure Functions-projekt från kommandoraden. Om du redan rensade resurser i slutet av artikeln går du igenom stegen igen för att återskapa funktionsappen och relaterade resurser i Azure.

Innan du börjar måste du slutföra artikeln Snabbstart: Skapa ett Azure Functions-projekt från kommandoraden. Om du redan rensade resurser i slutet av artikeln går du igenom stegen igen för att återskapa funktionsappen och relaterade resurser i Azure.

Hämta den Azure Storage anslutningssträngen

Tidigare skapade du ett Azure Storage-konto för användning av funktionsappen. Anslutningssträngen för det här kontot lagras säkert i appinställningarna i Azure. Genom att ladda ned inställningen tilllocal.settings.js på filen kan du använda den anslutningsskrivningen till en Storage-kö i samma konto när du kör funktionen lokalt.

  1. Kör följande kommando från projektroten och ersätt med namnet <APP_NAME> på funktionsappen från föregående snabbstart. 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 , som är AzureWebJobsStorage Storage-kontoanslutningssträngen. Du använder namnet och AzureWebJobsStorage anslutningssträngen i andra avsnitt i den här artikeln.

Viktigt

Eftersom local.settings.jspå innehåller hemligheter som laddats ned från Azure ska du alltid undanta den här filen från källkontrollen. Filen .gitignore som skapas med ett lokalt funktionsprojekt undantar filen som standard.

Registrera bindningstillägg

Med undantag för HTTP- och timerutlösare implementeras bindningar som tilläggspaket. Kör följande dotnet add package-kommando i terminalfönstret för att lägga Storage-tilläggspaketet i projektet.

dotnet add package Microsoft.Azure.WebJobs.Extensions.Storage 

Nu kan du lägga till lagringsutdatabindningen 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#-projekt definieras bindningarna som bindningsattribut för funktionsmetoden. Specifika definitioner beror på om din app körs i processen (C#-klassbiblioteket) eller i en isolerad process.

Öppna projektfilen HttpExample.cs och lägg till följande parameter i Run metoddefinitionen:

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

Parametern msg är en typ som representerar en samling meddelanden som skrivs till en ICollector<T> utdatabindning när funktionen har slutförts. I det här fallet är utdata en lagringskö med namnet outqueue . Anslutningssträngen för Storage-kontot anges av StorageAccountAttribute . Det här attributet anger inställningen som innehåller Storage-kontoanslutningssträngen och kan tillämpas på klass-, metod- eller parameternivå. I det här fallet kan du utelämna eftersom StorageAccountAttribute du redan använder standardlagringskontot.

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

Mer information om bindningar finns i Azure Functions och bindningar samt konfiguration av köutdata.

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 så att den matchar följande kod och lägg till msg parametern i funktionsdefinitionen msg.set(name) och under -instruktionen. if name:

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
        )

Parametern msg är en instans av azure.functions.Out class . Dess set -metod skriver ett strängmeddelande till kön, i det här fallet det namn som skickas 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 utdatabindningsobjektet för att skapa ett kö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));
}

Nu bör funktionen 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);

Observera att du inte behöver skriva någon kod för autentisering, hämta en köreferens eller skriva data. Alla dessa integreringsuppgifter hanteras smidigt i Azure Functions och köutdatabindning.

Köra funktionen lokalt

  1. Kör din funktion genom att starta den lokala Azure Functions runtime-värden från mappen LocalFunctionProj :

    func start
    

    I slutet av utdata bör följande rader visas:

     ...
    
     Now listening on: http://0.0.0.0:7071
     Application started. Press Ctrl+C to shut down.
    
     Http Functions:
    
             HttpExample: [GET,POST] http://localhost:7071/api/HttpExample
     ...
    
     

    Anteckning

    Om HttpExample inte visas som du ser ovan, startade du förmodligen värden från utsidan av projektets rotmapp. I så fall kan du använda CTRL + C för att stoppa värden, navigera till projektets rotmapp och köra föregående kommando igen.

  2. Kopiera URL: en för din HttpExample funktion från utdata till en webbläsare och Lägg till frågesträngen och ?name=<YOUR_NAME> gör den fullständiga URL: en som http://localhost:7071/api/HttpExample?name=Functions . I webbläsaren ska ett svarsmeddelande visas som visar att värdet för frågesträngen har återställts. Terminalen där du startade projektet visar också logg data när du gör förfrågningar.

  3. När du är klar använder du CTRL + C och väljer y att stoppa funktions värden.

Tips

Under starten hämtar värden och installerar lagrings bindnings tillägget och andra tillägg för Microsoft-bindning. Den här installationen sker eftersom bindnings tillägg är aktiverade som standard i host.jspå filen med följande egenskaper:

{
    "version": "2.0",
    "extensionBundle": {
        "id": "Microsoft.Azure.Functions.ExtensionBundle",
        "version": "[1.*, 2.0.0)"
    }
}

Om du stöter på fel som rör bindnings tillägg, kontrollerar du att ovanstående egenskaper finns i host.jspå.

Visa meddelandet i Azure Storage kö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.

Distribuera om projektet till Azure

Nu när du har verifierat lokalt att funktionen skrev ett meddelande till Azure Storage-kön kan du distribuera om projektet för att uppdatera slutpunkten som körs i Azure.

I mappen LocalFunctionsProj använder du kommandot för att distribuera om projektet och ersätta func azure functionapp publish med namnet på din <APP_NAME> app.

func azure functionapp publish <APP_NAME>

I den lokala projektmappen använder du följande Maven-kommando för att publicera om projektet:

mvn azure-functions:deploy

Verifiera i Azure

  1. Precis som i föregående snabbstart använder du en webbläsare eller CURL för att testa den omdistribuerade funktionen.

    Kopiera den fullständiga Invoke URL (Anropa URL) som visas i utdata från publiceringskommandot till ett adressfält i webbläsaren och lägga till frågeparametern &name=Functions . Webbläsaren bör visa liknande utdata som när du körde funktionen lokalt.

    Utdata från funktionen körs på Azure i en webbläsare

  2. Granska Storage kön igen, enligt beskrivningen i föregående avsnitt, för att kontrollera att den innehåller det nya meddelandet som skrivits till kön.

Rensa resurser

När du är klar använder du följande kommando för att ta bort resursgruppen och alla dess inneslutna resurser för att undvika ytterligare kostnader.

az group delete --name AzureFunctionsQuickstart-rg

Nästa steg

Du har uppdaterat din HTTP-utlösta funktion för att skriva data till en Storage kö. Nu kan du lära dig mer om att utveckla funktioner från kommandoraden med hjälp av Core Tools och Azure CLI: