Esercizio: Elaborare gli eventi e archiviare i dati in Azure Cosmos DB
Una seconda funzione può restare in ascolto degli eventi dello spazio dei nomi specifico nell'hub eventi di Azure ed elaborarli e archiviarli in un database creato con Azure Cosmos DB.
Creare un database con Azure Cosmos DB
Per creare il database, usare il comando az cosmosdb create
. Il comando usa un account Azure Cosmos DB, un database e un contenitore SQL.
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'
Per questo scenario, la temperatura è interessante. Quindi si definisce temperatureStatus
come chiave di partizione.
Compilare, configurare e distribuire un'altra funzione di Azure
Con gli hub eventi, è possibile iniziare con i flussi di dati in megabyte per poi aumentare a gigabyte o terabyte. La funzionalità di aumento automatico è una delle numerose opzioni disponibili per dimensionare il numero di unità elaborate in modo da soddisfare le esigenze di utilizzo.
Le applicazioni consumer per ogni funzione hanno una vista separata del flusso di eventi. I consumer leggono il flusso in modo indipendente in base al proprio ritmo e con offset specifici.
Per questo scenario viene creata una funzione consumer di Azure come esempio. La funzione, creata seguendo le procedure consigliate, deve essere indipendente, con il proprio account di archiviazione e le associazioni per l'accoppiamento libero e la scalabilità.
az storage account create \
--resource-group $RESOURCE_GROUP \
--name $STORAGE_ACCOUNT"c" \
--sku Standard_LRS
az functionapp create \
--resource-group $RESOURCE_GROUP \
--name $FUNCTION_APP"-c"\
--storage-account $STORAGE_ACCOUNT"c" \
--consumption-plan-location $LOCATION \
--runtime java \
--functions-version 4
Recuperare le stringhe di connessione
La funzione consumer deve essere in grado di riconoscere il proprio account di archiviazione e l'hub eventi. Deve inoltre essere sensibile al database in cui scrive gli eventi elaborati.
AZURE_WEB_JOBS_STORAGE=$( \
az storage account show-connection-string \
--resource-group $RESOURCE_GROUP \
--name $STORAGE_ACCOUNT"c" \
--query connectionString \
--output tsv)
echo $AZURE_WEB_JOBS_STORAGE
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
È possibile usare il comando echo $EVENT_HUB_CONNECTION_STRING
per verificare se la variabile è ancora impostata correttamente. In caso contrario, eseguire di nuovo il comando seguente:
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
Queste stringhe di connessione devono essere archiviate nelle impostazioni dell'applicazione per l'account Funzioni di Azure.
az functionapp config appsettings set \
--resource-group $RESOURCE_GROUP \
--name $FUNCTION_APP"-c" \
--settings \
AzureWebJobsStorage=$AZURE_WEB_JOBS_STORAGE \
EventHubConnectionString=$EVENT_HUB_CONNECTION_STRING \
CosmosDBConnectionString=$COSMOS_DB_CONNECTION_STRING
Nota
Per gli ambienti di produzione, è possibile usare un'istanza di Azure Key Vault per archiviare e gestire le stringhe di connessione.
Creare l'applicazione Funzioni
Prima di creare la funzione successiva, assicurarsi di essere nella cartella corretta.
cd ..
mvn archetype:generate --batch-mode \
-DarchetypeGroupId=com.microsoft.azure \
-DarchetypeArtifactId=azure-functions-archetype \
-DappName=$FUNCTION_APP"-c" \
-DresourceGroup=$RESOURCE_GROUP \
-DappRegion=$LOCATION \
-DappServicePlanName=$LOCATION"plan" \
-DgroupId=com.learn \
-DartifactId=telemetry-functions-consumer
Il comando crea un'applicazione come nell'ultimo esercizio. Si eliminano i file di test, si aggiorna local.settings.file
con il comando fetch-app-settings
e quindi si sostituisce il file Function.java
esistente.
cd telemetry-functions-consumer
rm -r src/test
Aggiornare le impostazioni locali per l'esecuzione e il debug locali.
func azure functionapp fetch-app-settings $FUNCTION_APP"-c"
Quindi, aprire il file Function.java
e sostituirne il contenuto con il codice seguente:
package com.learn;
import com.learn.TelemetryItem.status;
import com.microsoft.azure.functions.annotation.FunctionName;
import com.microsoft.azure.functions.ExecutionContext;
import com.microsoft.azure.functions.OutputBinding;
import com.microsoft.azure.functions.annotation.Cardinality;
import com.microsoft.azure.functions.annotation.CosmosDBOutput;
import com.microsoft.azure.functions.annotation.EventHubTrigger;
public class Function {
@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",
collectionName = "TelemetryInfo",
connectionStringSetting = "CosmosDBConnectionString")
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);
}
}
Creare un altro nuovo file denominato TelemetryItem.java nello stesso percorso di Function.java e aggiungere il codice seguente:
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;
}
}
Quando l'hub eventi riceve il messaggio, genera un evento. La funzione processSensorData
viene eseguita quando riceve l'evento. Elabora quindi i dati dell'evento e usa un'associazione di output di Azure Cosmos DB per inviare i risultati al database. Si usa nuovamente la classe TelemetryItem.java
. Gli oggetti TelemetryItem
possono essere considerati come il contratto gestito dal consumer tra i partecipanti di questo sistema guidato dagli eventi.
Eseguire localmente
Con Funzioni di Azure è possibile ricevere eventi da tutto il mondo. Sì, è anche possibile ricevere eventi localmente nel proprio computer di sviluppo.
mvn clean package
mvn azure-functions:run
Dopo i messaggi di compilazione e di avvio, vengono visualizzati gli eventi in ingresso quando viene eseguita la funzione:
[2021-01-19T16:45:24.709Z] Executing 'Functions.processSensorData' (Reason='(null)', Id=87354afa-abf4-4963-bd44-0c1421048240)
[2021-01-19T16:45:24.712Z] Event hub message received: TelemetryItem={id=null,temperature=21.653044570769897,pressure=36.061288095436126}
[2021-01-19T16:45:24.712Z] Function "processSensorData" (Id: 87354afa-abf4-4963-bd44-0c1421048240) invoked by Java Worker
Nel portale di Azure passare al proprio account Azure Cosmos DB. Selezionare Esplora dati, TelemetryInfo e quindi Elementi per visualizzare i dati quando arrivano.
Distribuire in Azure
A questo punto, è possibile spostare l'intero carico di lavoro nel cloud. Per distribuire le funzioni in Funzioni di Azure, usare il comando mvn azure-functions:deploy
di Maven. Assicurarsi di essere ancora nel repository corretto, telemetry-functions.
mvn azure-functions:deploy
Ottimo! L'intero scenario di telemetria è stato distribuito inviando i dati a un hub eventi e usando i dati con una funzione indipendente diversa. La funzione elabora i dati e poi archivia il risultato in un database creato con Azure Cosmos DB. Come è possibile verificare che l'applicazione soddisfi i requisiti predefiniti? Usando il monitoraggio.