Ejercicio: Creación de una función de Azure para simular datos de telemetría

Completado

Para nuestro ejemplo, usaremos el modelo de aprovisionamiento de eventos. Vamos a crear una función que simula datos telemétricos y enviarlos a un centro de eventos. Más adelante, otra función puede escuchar este evento y procesarlo y almacenarlo en una base de datos creada con Azure Cosmos DB.

Visualización del modelo de aprovisionamiento de eventos para pedir un café en una cafetería.

Preparación del entorno

Vamos a definir algunas variables de entorno para mantener los siguientes comandos lo más breves y comprensibles posible. Defina los <value> marcadores de posición y pegue y ejecute los siguientes comandos en el terminal o la herramienta de línea de comandos:

RESOURCE_GROUP=<value>
EVENT_HUB_NAMESPACE=<value>
EVENT_HUB_NAME=<value>
EVENT_HUB_AUTHORIZATION_RULE=<value>
COSMOS_DB_ACCOUNT=<value>
STORAGE_ACCOUNT=<value>
FUNCTION_APP=<value>
LOCATION=<value>

Nota:

Para establecer la variable LOCATION, puede comprobar el az functionapp list-consumption-locations comando y usar la ubicación más cercana.

Creación de los componentes necesarios

El aprovisionamiento de los recursos en Azure tarda algún tiempo. Comencemos con la creación del componente lo antes posible para evitar largas esperas más adelante.

Creación de un grupo de recursos

Siempre es una buena idea enlazar todos los recursos de un entrenamiento, una prueba de concepto o un prototipo en un grupo de recursos. De este modo, puede limpiar convenientemente todos los servicios usados con un comando. Para crear un grupo de recursos en la ubicación especificada, ejecute el siguiente comando en el terminal:

az group create \
    --name $RESOURCE_GROUP \
    --location $LOCATION

Creación y configuración de un centro de eventos

Para el centro de eventos, es necesario especificar el espacio de nombres en el que debe realizar la escucha. Además, debe configurar la regla de autorización en Listen y Send.

az eventhubs namespace create \
    --resource-group $RESOURCE_GROUP \
    --name $EVENT_HUB_NAMESPACE
az eventhubs eventhub create \
    --resource-group $RESOURCE_GROUP \
    --name $EVENT_HUB_NAME \
    --namespace-name $EVENT_HUB_NAMESPACE \
az eventhubs eventhub authorization-rule create \
    --resource-group $RESOURCE_GROUP \
    --name $EVENT_HUB_AUTHORIZATION_RULE \
    --eventhub-name $EVENT_HUB_NAME \
    --namespace-name $EVENT_HUB_NAMESPACE \
    --rights Listen Send

Compilación, configuración e implementación de la función de Azure

Para que este ejemplo sea lo más realista posible, cree una función de Azure y simule datos telemétricos. También puede enlazar un dispositivo IoT a la función de Azure, que luego tomaría datos reales. Dado que esta función es la que produce eventos, vamos a agregar una marca p o -p .

az storage account create \
    --resource-group $RESOURCE_GROUP \
    --name $STORAGE_ACCOUNT"p" \
    --sku Standard_LRS
az functionapp create \
    --resource-group $RESOURCE_GROUP \
    --name $FUNCTION_APP"-p"\
    --storage-account $STORAGE_ACCOUNT"p" \
    --consumption-plan-location $LOCATION \
    --runtime java \
    --functions-version 4

Nota:

El uso de functions-version 4 como 2 y 3 quedó en desuso en diciembre de 2022.

Cuando el comando az functionapp create crea tu aplicación de funciones, también crea un recurso de Application Insights con el mismo nombre. Usamos ese recurso más adelante para la supervisión.

Para recuperar las cadenas de conexión de la cuenta de almacenamiento y el centro de eventos, use los siguientes comandos para guardarlas en variables de entorno y, a continuación, mostrarlas con el echo comando .

AZURE_WEB_JOBS_STORAGE=$( \
    az storage account show-connection-string \
        --resource-group $RESOURCE_GROUP \
        --name $STORAGE_ACCOUNT"p" \
        --query connectionString \
        --output tsv)
echo $AZURE_WEB_JOBS_STORAGE
EVENT_HUB_CONNECTION_STRING=$( \
    az eventhubs eventhub authorization-rule keys list \
        --resource-group $RESOURCE_GROUP \
        --name $EVENT_HUB_AUTHORIZATION_RULE \
        --eventhub-name $EVENT_HUB_NAME \
        --namespace-name $EVENT_HUB_NAMESPACE \
        --query primaryConnectionString \
        --output tsv)
echo $EVENT_HUB_CONNECTION_STRING

Para almacenar las cadenas de conexión en la configuración de la aplicación de la cuenta de Azure Functions, ejecute el siguiente comando en el terminal:

az functionapp config appsettings set \
    --resource-group $RESOURCE_GROUP \
    --name $FUNCTION_APP"-p" \
    --settings \
        AzureWebJobsStorage=$AZURE_WEB_JOBS_STORAGE \
        EventHubConnectionString=$EVENT_HUB_CONNECTION_STRING

Ahora, el centro de eventos de recursos de Azure y la función de Azure se crean y configuran para que funcionen correctamente juntos.

A continuación, cree un proyecto de funciones locales con Maven.

mvn archetype:generate --batch-mode \
    -DarchetypeGroupId=com.microsoft.azure \
    -DarchetypeArtifactId=azure-functions-archetype \
    -DappName=$FUNCTION_APP"-p" \
    -DresourceGroup=$RESOURCE_GROUP \
    -DappRegion=$LOCATION \
    -DappServicePlanName=$LOCATION"plan" \
    -DgroupId=com.learn \
    -DartifactId=telemetry-functions-producer

Este comando genera varios archivos dentro de una carpeta de telemetry-functions-producer:

  • Archivo de compilación pom.xml con dependencias predefinidas de Azure.
  • Archivo local.settings.json que contiene la configuración de la aplicación para la implementación local y las pruebas manuales.
  • Un host.json archivo que habilita el paquete de extensiones de Azure Functions.
  • Archivo Function.java que incluye la función de desencadenador HTTP predeterminada.
  • Algunos archivos de prueba que este módulo de Learn no usa.

No tocamos los archivos de prueba de este módulo de Learn, así que no dude en eliminarlos.

cd telemetry-functions-producer
rm -r src/test

Para la ejecución local, la configuración de la aplicación debe recuperarse y almacenarse en el local.settings.json archivo. Para ello, ejecute el fetch-app-settings comando automáticamente.

func azure functionapp fetch-app-settings $FUNCTION_APP"-p"

A continuación, abra el Function.java archivo y reemplace el contenido por el código siguiente:

package com.learn;

import com.microsoft.azure.functions.annotation.EventHubOutput;
import com.microsoft.azure.functions.annotation.FunctionName;
import com.microsoft.azure.functions.annotation.TimerTrigger;
import com.microsoft.azure.functions.ExecutionContext;
public class Function {

    @FunctionName("generateSensorData")
    @EventHubOutput(
        name = "event",
        eventHubName = "", // blank because the value is included in the connection string
        connection = "EventHubConnectionString")
    public TelemetryItem generateSensorData(
        @TimerTrigger(
            name = "timerInfo",
            schedule = "*/10 * * * * *") // every 10 seconds
            String timerInfo,
        final ExecutionContext context) {
            context.getLogger().info("Java Timer trigger function executed at: " + java.time.LocalDateTime.now());
            double temperature = Math.random() * 100;
            double pressure = Math.random() * 50;
        return new TelemetryItem(temperature, pressure);
    }
}

La función generateSensorData simula un sensor que envía lecturas de temperatura y presión al centro de eventos. Un desencadenador de temporizador ejecuta la función cada 10 segundos y un enlace de salida del centro de eventos envía el valor devuelto al centro de eventos.

Cuando el centro de eventos recibe el mensaje, genera un evento.

Los datos usados por esta función se almacenan mediante una clase denominada TelemetryItem, que debe implementar. Cree un nuevo archivo denominado TelemetryItem.java en la misma ubicación que Function.java y agregue el código siguiente:

package com.learn;

public class TelemetryItem {

    private String id;
    private double temperature;
    private double pressure;
    private boolean isNormalPressure;
    private status temperatureStatus;
    static enum status {
        COOL,
        WARM,
        HOT
    }

    public TelemetryItem(double temperature, double pressure) {
        this.temperature = temperature;
        this.pressure = pressure;
    }

    public String getId() {
        return id;
    }

    public double getTemperature() {
        return temperature;
    }

    public double getPressure() {
        return pressure;
    }

    @Override
    public String toString() {
        return "TelemetryItem={id=" + id + ",temperature="
            + temperature + ",pressure=" + pressure + "}";
    }

    public boolean isNormalPressure() {
        return isNormalPressure;
    }

    public void setNormalPressure(boolean isNormal) {
        this.isNormalPressure = isNormal;
    }

    public status getTemperatureStatus() {
        return temperatureStatus;
    }

    public void setTemperatureStatus(status temperatureStatus) {
        this.temperatureStatus = temperatureStatus;
    }
}

Ejecución en modo local

Cuando se ejecutan funciones de Azure localmente, ya se transmiten por todo el mundo. Además, puede revisarlos en Azure Portal.

mvn clean package
mvn azure-functions:run

Después de algunos mensajes de compilación e inicio, verá una salida similar al ejemplo siguiente para cada vez que se ejecutan las funciones:

[2021-01-19T16:25:40.005Z] Executing 'Functions.generateSensorData' (Reason='Timer fired at 2021-01-19T17:25:40.0044630+01:00', Id=fcf567a3-03ec-4159-9714-aa4449861b30)
[2021-01-19T16:25:40.011Z] Java Timer trigger function executed at: 2021-01-19T17:25:40.009405
[2021-01-19T16:25:40.013Z] Function "generateSensorData" (Id: fcf567a3-03ec-4159-9714-aa4449861b30) invoked by Java Worker
[2021-01-19T16:25:40.048Z] Executed 'Functions.generateSensorData' (Succeeded, Id=fcf567a3-03ec-4159-9714-aa4449861b30, Duration=43ms)

Nota:

Antes de implementar y ejecutar la función en la nube de Azure, puede enviar eventos desde la máquina local en todo el mundo. Esto es muy útil para desarrollar, depurar y realizar pruebas locales.

Implementación en Azure

Desencadene la implementación en Azure ejecutando el mvn azure-functions:deploy comando y continúe.

mvn azure-functions:deploy