Připojení Azure Functions k Azure Storage pomocí nástrojů příkazového řádku

V tomto článku integrujete frontu Azure Storage s funkcí a účtem úložiště, který jste vytvořili v předchozím článku pro rychlý start. Této integrace dosáhnete pomocí výstupní vazby, která zapisuje data z požadavku HTTP do zprávy ve frontě. Dokončením tohoto článku se neúčtují žádné další náklady nad rámec několika centů USD předchozího rychlého startu. Další informace o vazbách najdete v tématu koncepty triggerů a vazeb Azure Functions.

Konfigurace místního prostředí

Než začnete, musíte dokončit článek Quickstart: Vytvoření Azure Functions project z příkazového řádku. Pokud jste už na konci tohoto článku vyčistili prostředky, projděte si kroky znovu a vytvořte aplikaci Function a související prostředky v Azure.

Než začnete, musíte dokončit článek Quickstart: Vytvoření Azure Functions project z příkazového řádku. Pokud jste už na konci tohoto článku vyčistili prostředky, projděte si kroky znovu a vytvořte aplikaci Function a související prostředky v Azure.

Než začnete, musíte dokončit článek Quickstart: Vytvoření Azure Functions project z příkazového řádku. Pokud jste už na konci tohoto článku vyčistili prostředky, projděte si kroky znovu a vytvořte aplikaci Function a související prostředky v Azure.

Než začnete, musíte dokončit článek Quickstart: Vytvoření Azure Functions project z příkazového řádku. Pokud jste už na konci tohoto článku vyčistili prostředky, projděte si kroky znovu a vytvořte aplikaci Function a související prostředky v Azure.

Než začnete, musíte dokončit článek Quickstart: Vytvoření Azure Functions project z příkazového řádku. Pokud jste už na konci tohoto článku vyčistili prostředky, projděte si kroky znovu a vytvořte aplikaci Function a související prostředky v Azure.

Než začnete, musíte dokončit článek Quickstart: Vytvoření Azure Functions project z příkazového řádku. Pokud jste už na konci tohoto článku vyčistili prostředky, projděte si kroky znovu a vytvořte aplikaci Function a související prostředky v Azure.

Načtěte připojovací řetězec Azure Storage

Důležité

Tento článek v současné době ukazuje, jak se připojit k účtu Azure Storage pomocí connection string, který obsahuje sdílený tajný klíč. Použití connection string usnadňuje ověření aktualizací dat v účtu storage. Pro zajištění nejlepšího zabezpečení byste místo toho měli při připojování k účtu storage používat spravované identity. Další informace naleznete v tématu Připojení v Příručce pro vývojáře.

Dříve jste vytvořili účet Azure Storage pro použití aplikace funkcí. Connection string pro tento účet se bezpečně uloží v nastavení aplikace v Azure. Stažením nastavení do souboru local.settings.json můžete, když funkce běží místně, použít připojení k zapisování do fronty úložiště ve stejném účtu.

  1. V kořenovém adresáři project spusťte následující příkaz a nahraďte <APP_NAME> názvem vaší aplikace funkcí z předchozího kroku. Tento příkaz přepíše všechny existující hodnoty v souboru.

    func azure functionapp fetch-app-settings <APP_NAME>
    
  2. Otevřete soubor local.settings.json a vyhledejte hodnotu s názvem AzureWebJobsStorage, což je connection string účtu Storage. Název AzureWebJobsStorage a připojovací řetězec použijete v jiných částech tohoto článku.

Důležité

Protože soubor local.settings.json obsahuje tajné kódy stažené z Azure, vždy tento soubor vylučte ze správy zdrojového kódu. Soubor .gitignore vytvořený s projektem místních funkcí standardně soubor vylučuje.

Registrace rozšíření vazeb

Kromě triggerů HTTP a časovače se vazby implementují jako balíčky rozšíření. Spuštěním následujícího příkazu dotnet add package v okně terminálu přidejte balíček rozšíření Storage do svého project.

dotnet add package Microsoft.Azure.Functions.Worker.Extensions.Storage.Queues --prerelease

Teď můžete do projektu přidat výstupní vazbu úložiště.

Přidání definice výstupní vazby do funkce

I když funkce může mít pouze jeden trigger, může mít více vstupních a výstupních vazeb, které vám umožní připojit se k dalším službám a prostředkům Azure bez psaní vlastního integračního kódu.

Při použití programovacího modelu Node.js v4 jsou atributy vazby definovány přímo v souboru ./src/functions/HttpExample.js . V předchozím rychlém startu už váš soubor obsahuje vazbu HTTP definovanou metodou app.http .

const { app } = require('@azure/functions');

app.http('httpTrigger', {
  methods: ['GET', 'POST'],
  authLevel: 'anonymous',
  handler: async (request, context) => {
    try {
      context.log(`Http function processed request for url "${request.url}"`);

      const name = request.query.get('name') || (await request.text());
      context.log(`Name: ${name}`);

      if (!name) {
        return { status: 404, body: 'Not Found' };
      }

      return { body: `Hello, ${name}!` };
    } catch (error) {
      context.log(`Error: ${error}`);
      return { status: 500, body: 'Internal Server Error' };
    }
  },
});

Při použití programovacího modelu Node.js v4 jsou atributy vazby definovány přímo v souboru ./src/functions/HttpExample.js . V předchozím rychlém startu už váš soubor obsahuje vazbu HTTP definovanou metodou app.http .

import {
  app,
  HttpRequest,
  HttpResponseInit,
  InvocationContext,
} from '@azure/functions';

export async function httpTrigger1(
  request: HttpRequest,
  context: InvocationContext,
): Promise<HttpResponseInit> {
  context.log(`Http function processed request for url "${request.url}"`);

  const name = request.query.get('name') || (await request.text()) || 'world';

  return { body: `Hello, ${name}!` };
}

app.http('httpTrigger1', {
  methods: ['GET', 'POST'],
  authLevel: 'anonymous',
  handler: httpTrigger1,
});

Tyto vazby deklarujete v souboru function.json ve složce funkce. V předchozím rychlém startu obsahuje váš soubor function.json ve složce HttpExample dvě vazby v kolekci bindings :

Při použití programovacího modelu Pythonu v2 jsou atributy vazby definovány přímo v souboru function_app.py jako dekorátory. V předchozím rychlém startu už váš soubor function_app.py obsahuje jednu vazbu založenou na dekorátoru:

import azure.functions as func
import logging

app = func.FunctionApp()

@app.function_name(name="HttpTrigger1")
@app.route(route="hello", auth_level=func.AuthLevel.ANONYMOUS)

Dekorátor route přidá do funkce vazbu HttpTrigger a HttpOutput, která umožní aktivaci vaší funkce, když požadavky HTTP narazí na zadanou trasu.

Pokud chcete zapisovat do fronty Azure Storage z této funkce, přidejte do kódu funkce queue_output dekorátor:

@app.queue_output(arg_name="msg", queue_name="outqueue", connection="AzureWebJobsStorage")

V dekorátoru arg_name identifikuje parametr vazby odkazovaný v kódu, queue_name je název fronty, do které vazba zapisuje, a connection je název nastavení aplikace, které obsahuje připojovací řetězec pro účet úložiště. V návodech k rychlému spuštění použijete stejný účet úložiště jako funkční aplikace, která je v nastavení AzureWebJobsStorage (ze souboru local.settings.json). queue_name Pokud neexistuje, vazba ji vytvoří při prvním použití.

"bindings": [
  {
    "authLevel": "function",
    "type": "httpTrigger",
    "direction": "in",
    "name": "Request",
    "methods": [
      "get",
      "post"
    ]
  },
  {
    "type": "http",
    "direction": "out",
    "name": "Response"
  }
]

Chcete-li zapsat do fronty Azure Storage:

  • Přidejte vlastnost do konfigurace vazby extraOutputs

    {
        methods: ['GET', 'POST'],
        extraOutputs: [sendToQueue], // add output binding to HTTP trigger
        authLevel: 'anonymous',
        handler: () => {}
    }
    
  • output.storageQueue Přidání funkce nad app.http volání

    const sendToQueue: StorageQueueOutput = output.storageQueue({
      queueName: 'outqueue',
      connection: 'AzureWebJobsStorage',
    });
    

Druhá vazba v kolekci má název res. Tato http vazba je výstupní vazba (out), která se používá k zápisu odpovědi HTTP.

Pokud chcete zapisovat do fronty Azure Storage z této funkce, přidejte out vazbu typu queue s názvem msg, jak je uvedeno v kódu níže.

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

Pro typ queue je nutné zadat název fronty v queueName a poskytnout název připojení Azure Storage (ze souboru local.settings.json) v connection.

V project jazyka C# jsou vazby definovány jako atributy vazby v metodě funkce. Konkrétní definice závisí na tom, jestli vaše aplikace běží v procesu (knihovna tříd C#) nebo v izolovaném pracovním procesu.

Otevřete soubor HttpExample.cs project a přidejte následující třídu MultiResponse:

public class MultiResponse
{
    [QueueOutput("outqueue", Connection = "AzureWebJobsStorage")]
    public string[] Messages { get; set; }
    public IActionResult HttpResponse { get; set; }
}

Třída MultiResponse umožňuje zapisovat do úložné fronty s názvem outqueue a úspěšnou zprávu HTTP. Do fronty může být odesláno více zpráv, protože atribut QueueOutput se použije na pole řetězců.

Vlastnost Connection nastaví připojovací řetězec pro účet úložiště. V tomto případě byste mohli vynechat Connection, protože už používáte výchozí účet storage.

V projektu Java jsou vazby definovány jako anotace pro vazby u funkce. Soubor function.json se pak automaticky vygeneruje na základě těchto poznámek.

Přejděte do umístění kódu funkce v části src/main/java, otevřete soubor Function.java project a do definice metody run přidejte následující parametr:

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

Parametr msg je typ OutputBinding<T>, který představuje kolekci řetězců. Tyto řetězce se po dokončení funkce zapisují jako zprávy do výstupní vazby. V tomto případě je výstupem fronta úložiště s názvem outqueue. Connection string pro účet Storage je nastavena metodou connection. Předáte nastavení aplikace, které obsahuje connection string úložišťového účtu, místo předávaní samotného connection stringu.

Definice run metody teď musí vypadat jako v následujícím příkladu:

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

Další informace o podrobnostech vazeb najdete v tématu Azure Functions koncepty triggerů a vazeb a konfigurace výstupů fronty.

Přidání kódu pro použití výstupní vazby

S definovanou vazbou fronty nyní můžete funkci aktualizovat tak, aby přijímala msg výstupní parametr a zapisovala zprávy do fronty.

Aktualizujte HttpExample\function_app.py tak, aby odpovídal následujícímu kódu, přidejte msg parametr do definice funkce a msg.set(name) pod příkaz if name: :

import azure.functions as func
import logging

app = func.FunctionApp(http_auth_level=func.AuthLevel.ANONYMOUS)

@app.route(route="HttpExample")
@app.queue_output(arg_name="msg", queue_name="outqueue", connection="AzureWebJobsStorage")
def HttpExample(req: func.HttpRequest, msg: func.Out [func.QueueMessage]) -> func.HttpResponse:
    logging.info('Python HTTP trigger function processed a request.')

    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}. This HTTP triggered function executed successfully.")
    else:
        return func.HttpResponse(
             "This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response.",
             status_code=200
        )

Parametr msg je instance azure.functions.Out class. Metoda set zapíše řetězcovou zprávu do fronty. V tomto případě je name předáno do funkce v řetězci dotazu adresy URL.

Přidejte kód, který používá výstupní vazební objekt context.extraOutputs k vytvoření zprávy do fronty. Přidejte tento kód před příkaz return.

context.extraOutputs.set(sendToQueue, [msg]);

V tomto okamžiku by vaše funkce mohla vypadat takto:

const { app, output } = require('@azure/functions');

const sendToQueue = output.storageQueue({
  queueName: 'outqueue',
  connection: 'AzureWebJobsStorage',
});

app.http('HttpExample', {
  methods: ['GET', 'POST'],
  authLevel: 'anonymous',
  extraOutputs: [sendToQueue],
  handler: async (request, context) => {
    try {
      context.log(`Http function processed request for url "${request.url}"`);

      const name = request.query.get('name') || (await request.text());
      context.log(`Name: ${name}`);

      if (name) {
        const msg = `Name passed to the function ${name}`;
        context.extraOutputs.set(sendToQueue, [msg]);
        return { body: msg };
      } else {
        context.log('Missing required data');
        return { status: 404, body: 'Missing required data' };
      }
    } catch (error) {
      context.log(`Error: ${error}`);
      return { status: 500, body: 'Internal Server Error' };
    }
  },
});

Přidejte kód, který používá výstupní vazební objekt context.extraOutputs k vytvoření zprávy do fronty. Přidejte tento kód před příkaz return.

context.extraOutputs.set(sendToQueue, [msg]);

V tomto okamžiku by vaše funkce mohla vypadat takto:

import {
  app,
  output,
  HttpRequest,
  HttpResponseInit,
  InvocationContext,
  StorageQueueOutput,
} from '@azure/functions';

const sendToQueue: StorageQueueOutput = output.storageQueue({
  queueName: 'outqueue',
  connection: 'AzureWebJobsStorage',
});

export async function HttpExample(
  request: HttpRequest,
  context: InvocationContext,
): Promise<HttpResponseInit> {
  try {
    context.log(`Http function processed request for url "${request.url}"`);

    const name = request.query.get('name') || (await request.text());
    context.log(`Name: ${name}`);

    if (name) {
      const msg = `Name passed to the function ${name}`;
      context.extraOutputs.set(sendToQueue, [msg]);
      return { body: msg };
    } else {
      context.log('Missing required data');
      return { status: 404, body: 'Missing required data' };
    }
  } catch (error) {
    context.log(`Error: ${error}`);
    return { status: 500, body: 'Internal Server Error' };
  }
}

app.http('HttpExample', {
  methods: ['GET', 'POST'],
  authLevel: 'anonymous',
  handler: HttpExample,
});

Přidejte kód, který pomocí rutiny Push-OutputBinding zapisuje text do fronty s využitím msg výstupní vazby. Před nastavením stavu OK v if příkazu přidejte tento kód.

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

V tomto okamžiku musí vaše funkce vypadat takto:

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

Nahraďte existující Run metodu následujícím kódem:

[Function("HttpExample")]
public MultiResponse Run([HttpTrigger(AuthorizationLevel.Function, "get", "post")] HttpRequest req)
{
    _logger.LogInformation("C# HTTP trigger function processed a request.");

    var message = "Welcome to Azure Functions!";

    // Return a response to both HTTP trigger and storage output binding.
    return new MultiResponse()
    {
        // Write a single message.
        Messages = new string[] { message },
        HttpResponse = new OkObjectResult(message)
    };
}

Teď můžete pomocí nového msg parametru zapisovat do výstupní vazby z kódu funkce. Před odpověď na úspěch přidejte následující řádek kódu, který přidá hodnotu name do msg výstupní vazby.

msg.setValue(name);

Při použití výstupní vazby nemusíte používat kód sady Azure Storage SDK k ověřování, získání reference na frontu nebo zápisu dat. Tyto úlohy za vás provádí běhové prostředí Functions a vazba výstupu fronty.

Vaše run metoda teď musí vypadat jako v následujícím příkladu:

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

Aktualizace testů

Vzhledem k tomu, že archetyp také vytvoří sadu testů, je nutné tyto testy aktualizovat, aby zvládly nový msg parametr v run podpisu metody.

Přejděte do umístění testovacího kódu v části src/test/java, otevřete soubor Function.java project a nahraďte řádek kódu pod //Invoke následujícím kódem:

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

Všimněte si, že nemusíte psát žádný kód pro ověřování, získání odkazu na frontu nebo zápis dat. Všechny tyto integrační úlohy jsou pohodlně zpracovány ve runtime Azure Functions a výstupní vazbě fronty.

Místní spuštění funkce

  1. Spusťte funkci spuštěním místního hostitele modulu runtime Azure Functions ze složky LocalFunctionProj.

    func start
    

    Na konci výstupu se musí zobrazit následující řádky:

    Screenshot výstupu okna terminálu při spuštění funkce místně.

    Poznámka:

    Pokud se httpExample nezobrazí, jak je znázorněno výše, pravděpodobně jste hostitele spustili mimo kořenovou složku project. V takovém případě pomocí Ctrl+C zastavte hostitele, přejděte do kořenové složky project a spusťte předchozí příkaz znovu.

  2. Zkopírujte adresu URL funkce HTTP z tohoto výstupu do prohlížeče a připojte řetězec ?name=<YOUR_NAME>dotazu, čímž se úplná adresa URL podobá http://localhost:7071/api/HttpExample?name=Functions. Prohlížeč by měl zobrazit zprávu s odpovědí, která odráží hodnotu query stringu. Terminál, ve kterém jste spustili projekt, také zobrazuje výstup protokolu během provádění požadavků.

  3. Až budete hotovi, stiskněte Ctrl+C a stisknutím kláves y zastavte hostitele funkcí.

Zobrazení zprávy ve frontě Azure Storage

Frontu můžete zobrazit v Azure portal nebo v Microsoft Azure Storage Explorer. Frontu můžete zobrazit také v Azure CLI, jak je popsáno v následujících krocích:

  1. Otevřete soubor local.setting.json projektu funkce a zkopírujte hodnotu connection string. V terminálu nebo příkazovém okně spuštěním následujícího příkazu vytvořte proměnnou prostředí s názvem AZURE_STORAGE_CONNECTION_STRING a vložte konkrétní connection string místo <MY_CONNECTION_STRING>. (Díky této proměnné prostředí nemusíte zadávat řetězec připojení veškerým následným příkazům pomocí argumentu --connection-string.)

    export AZURE_STORAGE_CONNECTION_STRING="<MY_CONNECTION_STRING>"
    
  2. (Volitelné) Použijte příkaz az storage queue list k zobrazení front služby Úložiště ve vašem účtu. Výstup z tohoto příkazu musí obsahovat frontu s názvem outqueue, která byla vytvořena při psaní první zprávy do této fronty.

    az storage queue list --output tsv
    
  3. Ke čtení zprávy z této fronty použijte příkaz az storage message get, což by měla být hodnota, kterou jste zadali při testování funkce dříve. Příkaz přečte a odebere první zprávu z fronty.

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

    Protože je text zprávy uložený base64 kódovaný, musí být zpráva před zobrazením dekódována. Po spuštění az storage message get se zpráva odebere z fronty. Pokud v ní byla jenom jedna zpráva outqueue, při druhém spuštění tohoto příkazu se zpráva nenačte a místo toho se zobrazí chyba.

Znovu nasaďte projekt na Azure

Po místním ověření, že funkce napsala zprávu do fronty Azure Storage, můžete znovu nasadit project a aktualizovat koncový bod spuštěný na Azure.

Ve složce LocalFunctionsProj použijte příkaz func azure functionapp publish k opětovnému nasazení project a nahraďte <APP_NAME> názvem vaší aplikace.

func azure functionapp publish <APP_NAME>

V místní složce project pomocí následujícího příkazu Maven znovu publikujte project:

mvn azure-functions:deploy

Ověření v Azure

  1. Stejně jako v předchozím rychlém startu použijte prohlížeč nebo CURL k otestování znovu nasazené funkce.

    Zkopírujte úplnou Invoke URL zobrazenou ve výstupu příkazu publish do adresního řádku prohlížeče a připojte dotazový parametr &name=Functions. Prohlížeč by měl zobrazit stejný výstup jako při místním spuštění funkce.

  2. Znovu zkontrolujte frontu úložiště, jak je popsáno v předchozí části, a ověřte, že obsahuje novou zprávu zapsanou do fronty.

Vyčištění prostředků

Po dokončení pomocí následujícího příkazu odstraňte skupinu prostředků a všechny její obsažené prostředky, abyste se vyhnuli dalším nákladům.

az group delete --name AzureFunctionsQuickstart-rg

Další kroky

Aktualizovali jste funkci aktivovanou protokolem HTTP tak, aby zapisovala data do Storage fronty. Teď se můžete dozvědět více o vývoji funkcí z příkazového řádku pomocí nástrojů Core Tools a Azure CLI: