Připojení Azure Functions do 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 rychlého startu. Tuto integraci 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 za pár usd v předchozím rychlém startu neúčtují žádné další náklady. 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 Rychlý start: Vytvoření projektu Azure Functions z příkazového řádku. Pokud jste už vyčistili prostředky na konci tohoto článku, projděte si kroky znovu a znovu vytvořte aplikaci funkcí a související prostředky v Azure.

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

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

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

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

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

Načtení připojovací řetězec služby Azure Storage

Dříve jste vytvořili účet Azure Storage pro použití aplikace funkcí. Připojovací řetězec pro tento účet se bezpečně uloží v nastavení aplikace v Azure. Stažením nastavení do souboru local.settings.json můžete při místním spuštění funkce použít připojení k zápisu do fronty služby Storage ve stejném účtu.

  1. V kořenovém adresáři projektu spusťte následující příkaz a nahraďte <APP_NAME> název 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 účet úložiště připojovací řetězec. Název AzureWebJobsStorage a připojovací řetězec použijete v jiných částech tohoto článku.

Důležité

Vzhledem k tomu, ž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ý pomocí projektu místních funkcí ve výchozím nastavení vyloučí soubor.

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í úložiště do projektu.

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ž může mít funkce 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 queue_output dekorátor do kódu funkce:

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

V dekorátoru identifikuje parametr vazby odkazovaný v kódu, queue_name je název fronty, do které vazba zapisuje, a connection je název nastavení aplikace, arg_name které obsahuje připojovací řetězec pro účet úložiště. V rychlých startech použijete stejný účet úložiště jako aplikace funkcí, která je v AzureWebJobsStorage nastavení (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"
  }
]

Zápis do fronty služby Azure Storage:

  • extraOutputs Přidání vlastnosti do konfigurace vazby

    {
        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 znázorněno v následujícím kódu:

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

queue Pro typ musíte zadat název fronty queueName a zadat název připojení azure Storage (ze souboru local.settings.json) do connectionsouboru .

V projektu 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 projektu HttpExample.cs a přidejte následující MultiResponse třídu:

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

Třída MultiResponse umožňuje zapisovat do fronty úložiště s názvem outqueue a zprávou o úspěchu PROTOKOLU HTTP. Do fronty může být odesláno více zpráv, protože QueueOutput se atribut 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 úložiště.

V projektu v Javě jsou vazby definovány jako poznámky k vazbám v metodě 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 src /main/java, otevřete soubor projektu Function.java a do definice metody přidejte následující parametr run :

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

Parametr msg je OutputBinding<T> typ, 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. Připojovací řetězec pro účet úložiště je nastavena metodouconnection. Předáte nastavení aplikace, které obsahuje připojovací řetězec účtu úložiště, a ne předání samotné připojovací řetězec.

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 Koncepty triggerů a vazeb Azure Functions a konfigurace výstupu fronty.

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

S definovanou vazbou fronty teď můžete funkci aktualizovat tak, aby přijímala msg výstupní parametr a zapisuje 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ě se jedná o předanou name funkci v řetězci dotazu adresy URL.

Přidejte kód, který používá objekt context.extraOutputs výstupní vazby k vytvoření zprávy 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á objekt context.extraOutputs výstupní vazby k vytvoření zprávy 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ý používá rutinu Push-OutputBinding k zápisu textu do fronty pomocí 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í HttpExample třídu následujícím kódem:

    [Function("HttpExample")]
    public static MultiResponse Run([HttpTrigger(AuthorizationLevel.Function, "get", "post")] HttpRequestData req,
        FunctionContext executionContext)
    {
        var logger = executionContext.GetLogger("HttpExample");
        logger.LogInformation("C# HTTP trigger function processed a request.");

        var message = "Welcome to Azure Functions!";

        var response = req.CreateResponse(HttpStatusCode.OK);
        response.Headers.Add("Content-Type", "text/plain; charset=utf-8");
        response.WriteString(message);

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

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 k ověřování používat kód sady SDK služby Azure Storage, získání odkazu na frontu nebo zápis dat. Tyto úlohy za vás provádí modul runtime služby Functions a výstupní vazba 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 souboru src/test/java, otevřete soubor projektu Function.java a nahraďte řádek kódu //Invoke pod 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 úlohy integrace se pohodlně zpracovávají v modulu 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:

    Snímek obrazovky s výstupem okna terminálu při místním spuštění funkce

    Poznámka:

    Pokud se httpExample nezobrazí, jak je znázorněno výše, pravděpodobně jste hostitele spustili mimo kořenovou složku projektu. V takovém případě pomocí ctrl+C zastavte hostitele, přejděte do kořenové složky projektu 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á vrací hodnotu řetězce dotazu. V terminálu, ve kterém jste spustili projekt, se při provádění požadavků zobrazuje také výstup protokolu.

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

Tip

Během spuštění hostitel stáhne a nainstaluje rozšíření vazby úložiště a další rozšíření vazeb Microsoftu. K této instalaci dochází, protože rozšíření vazeb jsou ve výchozím nastavení povolena v souboru host.json s následujícími vlastnostmi:

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

Pokud dojde k chybám souvisejícím s rozšířeními vazeb, zkontrolujte, jestli jsou uvedené výše uvedené vlastnosti v host.json.

Zobrazení zprávy ve frontě služby Azure Storage

Frontu můžete zobrazit na webu Azure Portal nebo v Průzkumník služby Microsoft Azure Storage. 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 připojovací řetězec. 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_STRINGa vložte konkrétní připojovací řetězec místo <MY_CONNECTION_STRING>. (Tato proměnná prostředí znamená, že nemusíte zadávat připojovací řetězec každému následnému příkazu pomocí argumentu--connection-string.)

    export AZURE_STORAGE_CONNECTION_STRING="<MY_CONNECTION_STRING>"
    
  2. (Volitelné) az storage queue list Pomocí příkazu zobrazte fronty služby Storage 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. az storage message get Pomocí příkazu si můžete přečíst zprávu z této fronty, což by měla být hodnota, kterou jste zadali při dřívějším testování funkce. 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`
    

    Vzhledem k tomu, že text zprávy je uložen s kódováním base64, musí být zpráva před zobrazením dekódována. Po spuštění az storage message getse 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.

Opětovné nasazení projektu do Azure

Teď, když jste místně ověřili, že funkce napsala zprávu do fronty Azure Storage, můžete projekt znovu nasadit a aktualizovat koncový bod spuštěný v Azure.

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

func azure functionapp publish <APP_NAME>

Ve složce místního projektu pomocí následujícího příkazu Maven znovu publikujte projekt:

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 adresu URL vyvolání zobrazené ve výstupu příkazu publish do adresního řádku prohlížeče a připojte parametr &name=Functionsdotazu . 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 fronty služby Storage. 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: