Conexión de Azure Functions a Azure Storage mediante Visual Studio Code

Azure Functions le permite conectar servicios de Azure y otros recursos a funciones sin tener que escribir su propio código de integración. Estos enlaces, que representan la entrada y la salida, se declaran dentro de la definición de función. Los datos de los enlaces se proporcionan a la función como parámetros. Un desencadenador es un tipo especial de enlace de entrada. Si bien una función tiene un único desencadenador, puede tener varios enlaces de entrada y salida. Para más información, consulte Conceptos básicos sobre los enlaces y desencadenadores de Azure Functions.

En este artículo se muestra cómo usar Visual Studio Code para conectar el servicio Azure Storage a la función que creó al completar el anterior artículo de inicio rápido. El enlace de salida que se agrega a esta función escribe datos de la solicitud HTTP en un mensaje de la cola de Azure Queue Storage.

La mayoría de los enlaces requieren una cadena de conexión almacenada que se usa en Functions para acceder al servicio enlazado. Para que el proceso sea más fácil, usará la cuenta de almacenamiento que creó junto con la aplicación de funciones. La conexión a esta cuenta ya está almacenada en una configuración de aplicación llamada AzureWebJobsStorage.

Nota:

Actualmente, en este artículo solo se da soporte técnico para Node.js v3 para Functions.

Configuración del entorno local

Antes de comenzar, deberá cumplir los siguientes requisitos:

En este artículo se da por supuesto que ya inició sesión en la suscripción de Azure desde Visual Studio Code. Puede iniciar sesión mediante la ejecución de Azure: Sign In desde la paleta de comandos.

Descarga de la configuración de la aplicación de función

En el artículo de inicio rápido anterior creó una aplicación de funciones en Azure junto con la cuenta de almacenamiento que se requería para ello. La cadena de conexión de esta cuenta se almacena de forma segura en la configuración de la aplicación en Azure. En este artículo, escribirá mensajes en una cola de almacenamiento de la misma cuenta. Si la función se ejecuta localmente, deberá descargar la configuración de la aplicación al archivo local.settings.json para conectarse a la cuenta de almacenamiento.

  1. Presione F1 para abrir la paleta de comandos y busque y ejecute el comando Azure Functions: Download Remote Settings....

  2. Elija la aplicación de funciones que creó en el artículo anterior. Seleccione Sí a todo para sobrescribir la configuración local existente.

    Importante

    El archivo local.settings.json contiene secretos, así que este nunca se publica y, además, se excluye de las características de control de código fuente.

  3. Copie el valor AzureWebJobsStorage, que constituye la clave del valor de la cadena de conexión de la cuenta de almacenamiento. Esta conexión se usa para comprobar que el enlace de salida funciona según lo previsto.

Registro de extensiones de enlace

Dado que está utilizando un enlace de salida de Queue Storage, para poder ejecutar el proyecto debe tener instalada la extensión de enlaces de Storage.

El proyecto se ha configurado para usar conjuntos de extensiones, que instalan automáticamente un conjunto predefinido de paquetes de extensiones.

Los conjuntos de extensiones ya están habilitados en el archivo host.json en la raíz del proyecto, que tiene un aspecto similar al siguiente ejemplo:

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

Ahora podrá agregar el enlace de salida de almacenamiento al proyecto.

Excepto los desencadenadores HTTP y del temporizador, los enlaces se implementan como paquetes de extensión. Ejecute el siguiente comando dotnet add package en la ventana Terminal para agregar el paquete de extensión de Storage al proyecto.

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

Ahora podrá agregar el enlace de salida de almacenamiento al proyecto.

Adición de un enlace de salida

En Funciones, cada tipo de enlace requiere un direction, type, y un único name. La manera de definir estos atributos depende del lenguaje de la aplicación de funciones.

Los atributos de enlace se definen en el archivo function.json para una función determinada. Según el tipo de enlace, pueden ser necesarias propiedades adicionales. En la configuración de salida de cola se describen los campos necesarios para un enlace de cola de Azure Storage. La extensión facilita la incorporación de enlaces al archivo function.json.

Para crear un enlace, haga clic con el botón derecho (Ctrl + clic en macOS) en el archivo function.json de la carpeta HttpTrigger y elija Agregar enlace... Siga las indicaciones para definir las siguientes propiedades de enlace para el nuevo enlace:

Prompt Valor Descripción
Select binding direction (Seleccionar dirección de enlace) out El enlace es un enlace de salida.
Select binding with direction... (Seleccionar enlace con dirección...) Azure Queue Storage El enlace es un enlace de cola de Azure Storage.
The name used to identify this binding in your code (Nombre identificativo del enlace en el código) msg Nombre que identifica el parámetro de enlace al que se hace referencia en el código.
The queue to which the message will be sent (Cola donde se enviará el mensaje) outqueue El nombre de la cola en la que escribe el enlace. Cuando no existe queueName, el enlace lo crea durante el primer uso.
Select setting from "local.setting.json" (Seleccionar configuración de "local.setting.json") AzureWebJobsStorage El nombre de una configuración de la aplicación que contiene la cadena de conexión de la cuenta de Storage. El valor AzureWebJobsStorage contiene la cadena de conexión de la cuenta de almacenamiento que creó con la aplicación de función.

Se agrega un enlace a la matriz bindings en function.json, que debería ser similar al siguiente:

{
  "type": "queue",
  "direction": "out",
  "name": "msg",
  "queueName": "outqueue",
  "connection": "AzureWebJobsStorage"
}

Los atributos de enlace se definen mediante la decoración de código de función específico en el archivo function_app.py. Use el decorador queue_output para agregar un enlace de salida de Azure Queue Storage.

Al usar el decorador queue_output, la dirección de enlace es implícitamente "out" y el tipo es Cola de Azure Storage. Agregue el siguiente decorador al código de función en HttpExample\function_app.py:

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

En este código, arg_name identifica el parámetro de enlace al que se hace referencia en el código, queue_name es el nombre de la cola en la que escribe el enlace y connection es el nombre de una configuración de la aplicación que contiene la cadena de conexión para la cuenta de Storage. En los inicios rápidos se usa la misma cuenta de almacenamiento que la aplicación de funciones, que se encuentra en la configuración AzureWebJobsStorage. Cuando no existe queue_name, el enlace lo crea durante el primer uso.

En un proyecto de C#, los enlaces se definen como atributos de enlace en el método de función. Las definiciones específicas dependen de si la aplicación se ejecuta en proceso (biblioteca de clases de C#) o en un proceso de trabajo aislado.

Abra el archivo de proyecto HttpExample.cs y agregue la siguiente clase MultiResponse:

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

La clase MultiResponse le permite escribir en una cola de almacenamiento denominada outqueue y en un mensaje HTTP de operación correcta. Como el atributo QueueOutput se aplica a una matriz de cadenas, se podrían enviar varios mensajes a la cola.

La propiedad Connection le permite establecer una cadena de conexión para la cuenta de almacenamiento. En este caso, puede omitir Connection, puesto que ya está usando la cuenta de almacenamiento predeterminada.

En un proyecto de Java, los enlaces se definen como anotaciones de enlace en el método de función. Entonces, el archivo function.json se genera automáticamente en función de estas anotaciones.

Vaya a la ubicación del código de función en src/main/java, abra el archivo de proyecto Function.java y agregue el parámetro siguiente a la definición del método run:

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

El parámetro msg es de tipo OutputBinding<T>, que representa una colección de cadenas escritas como mensajes en un enlace de salida cuando se completa la función. En este caso, la salida es una cola de almacenamiento denominada outqueue. La cadena de conexión de la cuenta de Storage la establece el método connection. En lugar de la propia cadena de conexión, el usuario se encarga de pasar la configuración de la aplicación que contiene la cadena de conexión de la cuenta de Storage.

La definición del método run debe ahora parecerse a la del siguiente ejemplo:

@FunctionName("HttpExample")
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) {

Adición de código que utilice el enlace de salida

Una vez definido el enlace, podrá usar el valor de name de este para acceder a él como atributo en la firma de función. Con un enlace de salida, no tiene que usar el código del SDK de Azure Storage para autenticarse, obtener una referencia de cola o escribir datos. El sistema en tiempo de ejecución de Functions y el enlace de salida de cola realizan esas tareas automáticamente.

Agregue código que utilice el objeto de enlace de salida msg en context.bindings para crear un mensaje de la cola. Agregue este código antes de la instrucción context.res.

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

En este momento, la función podría tener el aspecto siguiente:

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"
        };
    }
};

Agregue código que utilice el objeto de enlace de salida msg en context.bindings para crear un mensaje de la cola. Agregue este código antes de la instrucción context.res.

context.bindings.msg = name;

En este momento, la función debe tener el aspecto siguiente:

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;

Agregue código que use el cmdlet Push-OutputBinding para escribir texto en la cola mediante el enlace de salida msg. Agregue este código antes de establecer el estado correcto en la instrucción if.

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

En este momento, la función debe tener el aspecto siguiente:

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

Actualice HttpExample\function_app.py para que se ajuste al siguiente código y agregue el parámetro msg a la definición de la función y msg.set(name) en la instrucción 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
        )

El parámetro msg es una instancia de azure.functions.Out class. El método set escribe un mensaje de cadena en la cola. En este caso, es el name que pasa a la función en la cadena de consulta de URL.

Reemplace la clase HttpExample existente por el código siguiente:

    [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
        };
    }
}

Ahora, puede usar el nuevo parámetro msg para escribir en el enlace de salida desde el código de la función. Agregue la siguiente línea de código antes de la respuesta de operación correcta para agregar el valor de name al enlace de salida msg.

msg.setValue(name);

Al usar un enlace de salida, no tiene que usar el código del SDK de Azure Storage para autenticarse, obtener una referencia de cola o escribir datos. El sistema en tiempo de ejecución de Functions y el enlace de salida de cola realizan esas tareas automáticamente.

El método run debe ahora parecerse al del siguiente ejemplo:

@FunctionName("HttpExample")
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();
    }
}

Actualización de las pruebas

Dado que el arquetipo también crea un conjunto de pruebas, debe actualizar estas pruebas para controlar el nuevo parámetro msg en la signatura del método run.

Vaya a la ubicación del código de prueba en src/test/java, abra el archivo de proyecto Function.Java y reemplace la línea de código debajo de //Invoke por el código siguiente.

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

Ejecución local de la función

Visual Studio Code se integra con Azure Functions Core Tools para que pueda ejecutar este proyecto en un equipo de desarrollo local antes de publicarlo en Azure. Si aún no tiene instalado localmente Core Tools, se le pedirá que lo instale la primera vez que ejecute el proyecto.

  1. Para llamar a la función, presione F5 para iniciar el proyecto de aplicación de funciones. El panel Terminal muestra la salida de Core Tools. La aplicación se inicia en el panel Terminal. Puede ver el punto de conexión de la dirección URL de la función desencadenada por HTTP que se ejecuta localmente.

    Captura de pantalla de la salida de Visual Studio Code de la función local.

    Si aún no tiene Core Tools instalado, seleccione Instalar para instalar Core Tools cuando se le pida que lo haga.
    Si tiene problemas para ejecutarlo en Windows, asegúrese de que el terminal predeterminado de Visual Studio Code no esté establecido en WSL Bash.

  2. Mientras se ejecuta Core Tools, vaya al área Azure: Funciones. En Functions, expanda Proyecto local>Functions. Haga clic con el botón derecho (Windows) o Ctrl + clic en (macOS) en la función HttpExample y elija Execute Function Now... (Ejecutar la función ahora...).

    Captura de pantalla de la opción Ejecutar la función ahora de Visual Studio Code.

  3. En Escribir el cuerpo de la solicitud, presione la tecla ENTRAR para enviar un mensaje de solicitud a la función.

  4. Cuando la función se ejecuta localmente y devuelve una respuesta, se genera una notificación en Visual Studio Code. La información sobre la ejecución de la función se mostrará en el panel Terminal.

  5. Presione Ctrl + C para detener Core Tools y desconectar el depurador.

Ejecución local de la función

  1. Como en el artículo anterior, presione F5 para iniciar el proyecto de aplicación de función y Core Tools.

  2. Mientras se ejecuta Core Tools, vaya al área Azure: Funciones. En Functions, expanda Proyecto local>Functions. Haga clic con el botón derecho (Ctrl + clic en Mac) en la función HttpExample y elija Ejecutar la función ahora...

    Captura de pantalla de la función ejecutar desde Visual Studio Code.

  3. En Especificar el cuerpo de la solicitud, verá el valor { "name": "Azure" } en el cuerpo del mensaje de solicitud. Presione Entrar para enviar este mensaje de solicitud a la función.

  4. Una vez que se haya devuelto una respuesta, presione Ctrl + C para detener Core Tools.

Dado que está usando la cadena de conexión de almacenamiento, la función se conectará a la cuenta de almacenamiento de Azure durante la ejecución local. Cuando el enlace de salida se usa por primera vez, el entorno de ejecución de Functions crea una nueva cola denominada outqueue en la cuenta de almacenamiento. Usará el Explorador de Storage para comprobar que se han creado la cola y un mensaje.

Conexión del Explorador de Storage con la cuenta

Omita esta sección si ya instaló el Explorador de Azure Storage y lo conectó a su cuenta de Azure.

  1. Ejecute la herramienta Explorador de Azure Storage, y seleccione el icono de conexión de la izquierda y Agregar una cuenta.

    Captura de pantalla de cómo agregar una cuenta de Azure al Explorador de Microsoft Azure Storage.

  2. En el cuadro de diálogo Conectar, seleccione Agregar una cuenta de Azure y, a continuación, elija el entorno de Azure que quiera usar y seleccione Iniciar sesión...

    Captura de pantalla de la ventana de inicio de sesión en la cuenta de Azure.

Después de iniciar sesión correctamente en su cuenta, verá todas las suscripciones de Azure asociadas con ella. Elija la suscripción y selección Abrir Explorer.

Examen de la cola de salida

  1. En Visual Studio Code, presione la tecla F1 para abrir la paleta de comandos y, después, busque y ejecute el comando Azure Storage: Open in Storage Explorer y elija el nombre de la cuenta de almacenamiento que quiere usar. En el menú de la cuenta de almacenamiento, seleccione el Explorador de Azure Storage.

  2. Expanda el nodo Colas y, después, seleccione la cola con el nombre outqueue.

    La cola contiene el mensaje que creó el enlace de salida de la cola al ejecutar la función desencadenada por HTTP. Si se invoca la función con el valor predeterminado name de Azure, el mensaje de cola es Name passed to the function: Azure (Nombre pasado a la función: Azure).

    Captura de pantalla del mensaje de la cola que se muestra en el Explorador de Azure Storage.

  3. Vuelva a ejecutar la función y envíe otra solicitud. A continuación, verá que hay un nuevo mensaje en la cola.

Ahora, es el momento de volver a publicar la aplicación de función actualizada en Azure.

Reimplementación y comprobación de la aplicación actualizada

  1. En Visual Studio Code, presione F1 para abrir la paleta de comandos. En la paleta de comandos, busque y seleccione Azure Functions: Deploy to function app....

  2. Elija la aplicación de funciones que creó en el primer artículo. Dado que va a volver a implementar el proyecto en la misma aplicación, seleccione Implementar para descartar la advertencia sobre la sobrescritura de archivos.

  3. Una vez que haya finalizado la implementación, podrá volver a usar la característica Ejecutar la función ahora... para desencadenar la función en Azure.

  4. Vuelva a consultar el mensaje de la cola de almacenamiento para comprobar que el enlace de salida genera un nuevo mensaje en la cola.

Limpieza de recursos

En Azure, los recursos son aplicaciones de funciones, funciones o cuentas de almacenamiento, entre otros. Se agrupan en grupos de recursos y se puede eliminar todo el contenido de un grupo si este se elimina.

Para completar estas guías de inicio rápido, ha creado varios recursos. Se le pueden facturar por estos recursos, dependiendo del estado de la cuentade los y precios de los servicios. Si ya no necesita los recursos, aquí se indica cómo eliminarlos:

  1. En Visual Studio Code, presione F1 para abrir la paleta de comandos. En la paleta de comandos, busque y seleccione Azure: Open in portal.

  2. Elija una aplicación de funciones y presione la tecla ENTRAR. La página de la aplicación de funciones se abre en Azure Portal.

  3. En la pestaña Información general, seleccione el vínculo con nombre junto a Grupo de recursos.

    Captura de pantalla de la selección del grupo de recursos que se va a eliminar de la página de la aplicación de funciones.

  4. En la página Grupo de recursos, revise la lista de recursos incluidos y compruebe que estos sean los que desea eliminar.

  5. Seleccione Eliminar grupo de recursos y siga las instrucciones.

    El proceso de eliminación tardará un par de minutos. Cuando termine, aparece una notificación durante unos segundos. También puede seleccionar el icono de campana en la parte superior de la página para ver la notificación.

Pasos siguientes

Ha actualizado la función desencadenada por HTTP para escribir datos en una cola de almacenamiento. Ahora, puede obtener más información sobre el desarrollo de Functions mediante Visual Studio Code: