Ejercicio: Creación de una función de Azure para simular datos de telemetría
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.
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.xmlcon dependencias predefinidas de Azure. - Archivo
local.settings.jsonque contiene la configuración de la aplicación para la implementación local y las pruebas manuales. - Un
host.jsonarchivo que habilita el paquete de extensiones de Azure Functions. - Archivo
Function.javaque 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