Tutoriel : Créer une fonction en Java avec un déclencheur Event Hub et une liaison de sortie Azure Cosmos DB
Ce didacticiel explique comment utiliser Azure Functions pour créer une fonction Java qui analyse un flux continu de données de température et de pression. Les événements Event Hubs qui représentent les relevés du capteur déclenchent la fonction. La fonction traite les données d'événement, puis ajoute des entrées d'état à une instance d'Azure Cosmos DB.
Dans ce didacticiel, vous allez :
- Gérer et configurer des ressources Azure à l'aide de l'interface de ligne de commande Azure (Azure CLI)
- Créer et tester des fonctions Java qui interagissent avec ces ressources
- Déployer vos fonctions sur Azure et les surveiller à l'aide d'Application Insights
Si vous n’avez pas d’abonnement Azure, créez un compte gratuit Azure avant de commencer.
Prérequis
Pour suivre ce didacticiel, vous devez installer les ressources suivantes :
- Java Developer Kit (JDK), version 8
- Apache Maven, version 3.0 ou ultérieure
- Azure Functions Core Tools version 2.6.666 ou ultérieure
Utilisez l’environnement Bash dans Azure Cloud Shell. Pour plus d’informations, consultez Démarrage rapide pour Bash dans Azure Cloud Shell.
Si vous préférez exécuter les commandes de référence de l’interface de ligne de commande localement, installez l’interface Azure CLI. Si vous exécutez sur Windows ou macOS, envisagez d’exécuter Azure CLI dans un conteneur Docker. Pour plus d’informations, consultez Guide pratique pour exécuter Azure CLI dans un conteneur Docker.
Si vous utilisez une installation locale, connectez-vous à Azure CLI à l’aide de la commande az login. Pour finir le processus d’authentification, suivez les étapes affichées dans votre terminal. Pour connaître les autres options de connexion, consultez Se connecter avec Azure CLI.
Lorsque vous y êtes invité, installez l’extension Azure CLI lors de la première utilisation. Pour plus d’informations sur les extensions, consultez Utiliser des extensions avec Azure CLI.
Exécutez az version pour rechercher la version et les bibliothèques dépendantes installées. Pour effectuer une mise à niveau vers la dernière version, exécutez az upgrade.
Important
Pour suivre ce didacticiel, vous devez définir la variable d'environnement JAVA_HOME
sur l'emplacement d'installation du JDK.
Si vous préférez utiliser directement le code pour ce didacticiel, consultez le référentiel d'exemples java-functions-eventhub-cosmosdb.
Créer des ressources Azure
Dans ce didacticiel, vous aurez besoin des ressources suivantes :
- Un groupe de ressources pour contenir les autres ressources
- Un espace de noms Event Hubs, un hub d'événements et une règle d'autorisation
- Un compte, une base de données et une collection Azure Cosmos DB
- Une application de fonction et un compte de stockage pour l'héberger
Les sections suivantes expliquent comment créer ces ressources à l'aide de l'interface de ligne de commande Azure (Azure CLI).
Définir des variables d’environnement
Créez ensuite des variables d'environnement pour les noms et l'emplacement des ressources que vous allez créer. Utilisez les commandes suivantes, en remplaçant les espaces réservés <value>
par les valeurs de votre choix. Les valeurs doivent être conformes aux règles de nommage et aux restrictions applicables aux ressources Azure. Pour la variable LOCATION
, utilisez l'une des valeurs produites par la commande az functionapp list-consumption-locations
.
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>
Ces variables seront utilisées dans la suite de ce didacticiel. Sachez que ces variables ne persistent que pendant la durée de votre session Azure CLI ou Cloud Shell actuelle. Vous devrez réexécuter ces commandes si vous utilisez une autre fenêtre de terminal locale ou si votre session Cloud Shell expire.
Créer un groupe de ressources
Azure utilise des groupes de ressources pour collecter toutes les ressources associées dans votre compte. Vous disposez ainsi d'une visibilité globale sur celles-ci et pouvez les supprimer à l'aide d'une seule commande lorsque vous n'en avez plus besoin.
Utilisez la commande suivante pour créer un groupe de ressources :
Créer un hub d’événements
Créez ensuite un espace de noms Azure Event Hubs, un hub d'événements et une règle d'autorisation à l'aide des commandes suivantes :
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 \
--message-retention 1
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
L'espace de noms Event Hubs contient le hub d'événements réel et sa règle d'autorisation. La règle d'autorisation permet à vos fonctions d'envoyer des messages au hub et d'écouter les événements correspondants. Une fonction envoie des messages qui représentent des données de télémétrie. Une autre fonction écoute les événements, analyse leurs données et stocke les résultats dans Azure Cosmos DB.
Créer une base de données Azure Cosmos DB
Créez ensuite un compte, une base de données et une collection Azure Cosmos DB à l'aide des commandes suivantes :
az cosmosdb create \
--resource-group $RESOURCE_GROUP \
--name $COSMOS_DB_ACCOUNT
az cosmosdb sql database create \
--resource-group $RESOURCE_GROUP \
--account-name $COSMOS_DB_ACCOUNT \
--name TelemetryDb
az cosmosdb sql container create \
--resource-group $RESOURCE_GROUP \
--account-name $COSMOS_DB_ACCOUNT \
--database-name TelemetryDb \
--name TelemetryInfo \
--partition-key-path '/temperatureStatus'
La valeur partition-key-path
partitionne vos données en fonction de la valeur temperatureStatus
de chaque élément. La clé de partition permet à Azure Cosmos DB d'améliorer les performances en divisant vos données en sous-ensembles distincts accessibles de façon indépendante.
Créer un compte de stockage et une application de fonction
Créez ensuite un compte Stockage Azure, requis par Azure Functions, puis créez l'application de fonction. Utilisez les commandes suivantes :
az storage account create \
--resource-group $RESOURCE_GROUP \
--name $STORAGE_ACCOUNT \
--sku Standard_LRS
az functionapp create \
--resource-group $RESOURCE_GROUP \
--name $FUNCTION_APP \
--storage-account $STORAGE_ACCOUNT \
--consumption-plan-location $LOCATION \
--runtime java \
--functions-version 3
Lorsque la commande az functionapp create
crée votre application de fonction, elle crée également une ressource Application Insights du même nom. L'application de fonction est automatiquement configurée avec un paramètre nommé APPINSIGHTS_INSTRUMENTATIONKEY
qui la connecte à Application Insights. Vous pouvez afficher les données de télémétrie de l'application après avoir déployé vos fonctions sur Azure, comme décrit plus loin dans ce didacticiel.
Configurer votre application de fonction
Votre application de fonction doit avoir accès aux autres ressources pour fonctionner correctement. Les sections suivantes vous expliquent comment configurer votre application de fonction afin qu'elle puisse s'exécuter sur votre ordinateur local.
Récupérer les chaînes de connexion aux ressources
Utilisez les commandes suivantes pour récupérer les chaînes de connexion de stockage, de hub d'événements et de base de données Azure Cosmos DB, et les enregistrer dans les variables d'environnement :
AZURE_WEB_JOBS_STORAGE=$( \
az storage account show-connection-string \
--name $STORAGE_ACCOUNT \
--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
COSMOS_DB_CONNECTION_STRING=$( \
az cosmosdb keys list \
--resource-group $RESOURCE_GROUP \
--name $COSMOS_DB_ACCOUNT \
--type connection-strings \
--query 'connectionStrings[0].connectionString' \
--output tsv)
echo $COSMOS_DB_CONNECTION_STRING
Ces variables sont définies sur des valeurs récupérées à partir de commandes Azure CLI. Chaque commande utilise une requête JMESPath pour extraire la chaîne de connexion à partir de la charge JSON renvoyée. Les chaînes de connexion sont également affichées à l'aide de echo
pour vous permettre de vérifier qu'elles ont bien été récupérées.
Mettre à jour les paramètres de votre application de fonction
Utilisez ensuite la commande suivante pour transmettre les valeurs de chaîne de connexion aux paramètres de l'application sur votre compte Azure Functions :
az functionapp config appsettings set \
--resource-group $RESOURCE_GROUP \
--name $FUNCTION_APP \
--settings \
AzureWebJobsStorage=$AZURE_WEB_JOBS_STORAGE \
EventHubConnectionString=$EVENT_HUB_CONNECTION_STRING \
CosmosDBConnectionSetting=$COSMOS_DB_CONNECTION_STRING
Vos ressources Azure ont été créées et configurées pour fonctionner correctement ensemble.
Créer et tester vos fonctions
Vous allez ensuite créer un projet sur votre ordinateur local, ajouter du code Java et le tester. Vous allez utiliser des commandes qui fonctionnent avec le plug-in Azure Functions pour Maven et Azure Functions Core Tools. Vos fonctions seront exécutées localement, mais elles utiliseront les ressources cloud que vous avez créées. Lorsque les fonctions sont opérationnelles localement, vous pouvez utiliser Maven pour les déployer dans le cloud. Vous verrez alors vos données et analyses s'accumuler.
Si vous avez utilisé Cloud Shell pour créer vos ressources, vous ne serez pas connecté à Azure localement. Dans ce cas, utilisez la commande az login
pour lancer le processus de connexion basé sur un navigateur. Puis, si nécessaire, définissez l'abonnement par défaut sui az account set --subscription
, suivi de l'ID de l'abonnement. Enfin, exécutez les commandes suivantes pour recréer des variables d'environnement sur votre ordinateur local. Remplacez les espaces réservés <value>
par les valeurs que vous avez utilisées précédemment.
Créer un projet de fonctions local
Utilisez la commande Maven suivante pour créer un projet Functions et ajouter les dépendances requises.
mvn archetype:generate --batch-mode \
-DarchetypeGroupId=com.microsoft.azure \
-DarchetypeArtifactId=azure-functions-archetype \
-DappName=$FUNCTION_APP \
-DresourceGroup=$RESOURCE_GROUP \
-DappRegion=$LOCATION \
-DgroupId=com.example \
-DartifactId=telemetry-functions
Cette commande génère plusieurs fichiers dans un dossier telemetry-functions
:
- Un fichier
pom.xml
à utiliser avec Maven - Un fichier
local.settings.json
contenant les paramètres de l'application pour le test local - Un fichier
host.json
qui active le groupe d'extensions Azure Functions, requis pour la liaison de sortie Azure Cosmos DB dans votre fonction d'analyse de données - Un fichier
Function.java
incluant une implémentation de fonction par défaut - Quelques fichiers de test dont ce didacticiel n'a pas besoin
Pour éviter les erreurs de compilation, vous devez supprimer les fichiers de test. Exécutez les commandes suivantes pour accéder au dossier du nouveau projet et supprimer le dossier de test :
Récupérer les paramètres de votre application de fonction en vue d'une utilisation locale
Pour les tests locaux, votre projet de fonction aura besoin des chaînes de connexion que vous avez précédemment ajoutées à votre application de fonction dans Azure. Utilisez la commande Azure Functions Core Tools suivante, qui permet de récupérer tous les paramètres de l'application de fonction stockés dans le cloud et de les ajouter à votre fichier local.settings.json
:
Ajouter du code Java
Ouvrez ensuite le fichier Function.java
et remplacez son contenu par le code suivant.
package com.example;
import com.example.TelemetryItem.status;
import com.microsoft.azure.functions.annotation.Cardinality;
import com.microsoft.azure.functions.annotation.CosmosDBOutput;
import com.microsoft.azure.functions.annotation.EventHubOutput;
import com.microsoft.azure.functions.annotation.EventHubTrigger;
import com.microsoft.azure.functions.annotation.FunctionName;
import com.microsoft.azure.functions.annotation.TimerTrigger;
import com.microsoft.azure.functions.ExecutionContext;
import com.microsoft.azure.functions.OutputBinding;
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);
}
@FunctionName("processSensorData")
public void processSensorData(
@EventHubTrigger(
name = "msg",
eventHubName = "", // blank because the value is included in the connection string
cardinality = Cardinality.ONE,
connection = "EventHubConnectionString")
TelemetryItem item,
@CosmosDBOutput(
name = "databaseOutput",
databaseName = "TelemetryDb",
containerName = "TelemetryInfo",
connection = "CosmosDBConnectionSetting")
OutputBinding<TelemetryItem> document,
final ExecutionContext context) {
context.getLogger().info("Event hub message received: " + item.toString());
if (item.getPressure() > 30) {
item.setNormalPressure(false);
} else {
item.setNormalPressure(true);
}
if (item.getTemperature() < 40) {
item.setTemperatureStatus(status.COOL);
} else if (item.getTemperature() > 90) {
item.setTemperatureStatus(status.HOT);
} else {
item.setTemperatureStatus(status.WARM);
}
document.setValue(item);
}
}
Comme vous pouvez le constater, ce fichier contient deux fonctions : generateSensorData
et processSensorData
. La fonction generateSensorData
simule un capteur qui envoie des relevés de température et de pression au hub d'événements. Un déclencheur exécute la fonction toutes les 10 secondes et une liaison de sortie du hub d'événements transmet la valeur renvoyée au hub d'événements.
Lorsque le hub d'événements reçoit le message, il génère un événement. La fonction processSensorData
s'exécute lorsqu'il reçoit l'événement. Il traite ensuite les données d'événement et utilise une liaison de sortie Azure Cosmos DB pour envoyer les résultats à Azure Cosmos DB.
Les données utilisées par ces fonctions sont stockées à l'aide d'une classe appelée TelemetryItem
, que vous devez implémenter. Créez un nouveau fichier appelé TelemetryItem.java
au même emplacement que Function.java
, et ajoutez le code suivant :
package com.example;
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;
}
}
Exécution locale
Vous pouvez maintenant générer et exécuter les fonctions localement, et voir les données s'afficher dans votre instance d'Azure Cosmos DB.
Utilisez les commandes Maven suivantes pour générer et exécuter les fonctions :
Après quelques messages relatifs à la génération et au démarrage, une sortie semblable à l'exemple suivant s'affiche à chaque exécution des fonctions :
[10/22/19 4:01:30 AM] Executing 'Functions.generateSensorData' (Reason='Timer fired at 2019-10-21T21:01:30.0016769-07:00', Id=c1927c7f-4f70-4a78-83eb-bc077d838410)
[10/22/19 4:01:30 AM] Java Timer trigger function executed at: 2019-10-21T21:01:30.015
[10/22/19 4:01:30 AM] Function "generateSensorData" (Id: c1927c7f-4f70-4a78-83eb-bc077d838410) invoked by Java Worker
[10/22/19 4:01:30 AM] Executed 'Functions.generateSensorData' (Succeeded, Id=c1927c7f-4f70-4a78-83eb-bc077d838410)
[10/22/19 4:01:30 AM] Executing 'Functions.processSensorData' (Reason='', Id=f4c3b4d7-9576-45d0-9c6e-85646bb52122)
[10/22/19 4:01:30 AM] Event hub message received: TelemetryItem={id=null,temperature=32.728691307527015,pressure=10.122563042388165}
[10/22/19 4:01:30 AM] Function "processSensorData" (Id: f4c3b4d7-9576-45d0-9c6e-85646bb52122) invoked by Java Worker
[10/22/19 4:01:38 AM] Executed 'Functions.processSensorData' (Succeeded, Id=1cf0382b-0c98-4cc8-9240-ee2a2f71800d)
Vous pouvez ensuite rejoindre le portail Azure et accéder à votre compte Azure Cosmos DB. Sélectionnez Explorateur de données, développez TelemetryInfo, puis sélectionnez Éléments pour afficher vos données lors de leur arrivée.
Déployer sur Azure et consulter les données de télémétrie de l'application
Enfin, vous pouvez déployer votre application sur Azure et vérifier qu'elle continue à fonctionner de la même manière qu'en local.
Déployez votre projet sur Azure à l'aide de la commande suivante :
Vos fonctions s'exécutent désormais dans Azure, et continuent à accumuler des données dans votre instance d'Azure Cosmos DB. Vous pouvez voir votre application de fonction déployée sur le portail Azure, et consulter les données de télémétrie de l'application via la ressource Application Insights connectée, comme illustré dans les captures d'écran suivantes :
Flux de métriques temps réel :
Performances :
Nettoyer les ressources
Lorsque les ressources Azure que vous avez créées dans ce didacticiel ne vous sont plus d'aucune utilité, vous pouvez les supprimer à l'aide de la commande suivante :
Étapes suivantes
Dans ce didacticiel, vous avez appris à créer une fonction Azure qui gère les événements Event Hub et met à jour une instance d’Azure Cosmos DB. Pour plus d'informations, consultez le Guide des développeurs Java sur Azure Functions. Pour plus d'informations sur les annotations utilisées, consultez la référence com.microsoft.azure.functions.annotation.
Ce didacticiel a utilisé des variables d'environnement et des paramètres d'application pour stocker des secrets tels que des chaînes de connexion. Pour plus d'informations sur le stockage de ces secrets dans Azure Key Vault, consultez Utiliser des références Key Vault pour App Service et Azure Functions.
Apprenez ensuite à utiliser l'approche CI/CD Azure Pipelines dans le cadre d'un déploiement automatisé :