Share via


Tutorial: Erstellen einer Funktion in Java mit einem Event Hub-Trigger und einer Azure Cosmos DB-Ausgabebindung

In diesem Tutorial erfahren Sie, wie Sie mit Azure Functions eine Java-Funktion erstellen, die einen kontinuierlichen Datenstrom von Temperatur- und Druckdaten analysiert. Event Hub-Ereignisse, die Sensormesswerte darstellen, lösen die Funktion aus. Die Funktion verarbeitet die Ereignisdaten und fügt dann Statuseinträge zur Azure Cosmos Datenbankinstanz hinzu.

In diesem Tutorial gehen Sie wie folgt vor:

  • Sie erstellen und konfigurieren Azure-Ressourcen mit der Azure-Befehlszeilenschnittstelle.
  • Sie erstellen und testen Java-Funktionen, die mit diesen Ressourcen interagieren.
  • Sie stellen Ihre Funktionen in Azure bereit und überwachen sie mit Application Insights.

Wenn Sie kein Azure-Abonnement haben, erstellen Sie ein kostenloses Azure-Konto, bevor Sie beginnen.

Voraussetzungen

Für dieses Tutorial muss Folgendes installiert sein:

  • Verwenden Sie die Bash-Umgebung in Azure Cloud Shell. Weitere Informationen finden Sie unter Schnellstart für Bash in Azure Cloud Shell.

  • Wenn Sie CLI-Referenzbefehle lieber lokal ausführen, installieren Sie die Azure CLI. Wenn Sie Windows oder macOS ausführen, sollten Sie die Azure CLI in einem Docker-Container ausführen. Weitere Informationen finden Sie unter Ausführen der Azure CLI in einem Docker-Container.

    • Wenn Sie eine lokale Installation verwenden, melden Sie sich mithilfe des Befehls az login bei der Azure CLI an. Führen Sie die in Ihrem Terminal angezeigten Schritte aus, um den Authentifizierungsprozess abzuschließen. Informationen zu anderen Anmeldeoptionen finden Sie unter Anmelden mit der Azure CLI.

    • Installieren Sie die Azure CLI-Erweiterung beim ersten Einsatz, wenn Sie dazu aufgefordert werden. Weitere Informationen zu Erweiterungen finden Sie unter Verwenden von Erweiterungen mit der Azure CLI.

    • Führen Sie az version aus, um die installierte Version und die abhängigen Bibliotheken zu ermitteln. Führen Sie az upgrade aus, um das Upgrade auf die aktuelle Version durchzuführen.

Wichtig

Damit Sie dieses Tutorial durchführen können, muss die Umgebungsvariable JAVA_HOME auf den Installationsspeicherort des JDK festgelegt sein.

Wenn Sie es vorziehen, den Code für dieses Tutorial direkt zu verwenden, finden Sie die entsprechenden Informationen im Beispielrepository java-functions-eventhub-cosmosdb.

Erstellen von Azure-Ressourcen

In diesem Tutorial benötigen Sie folgende Ressourcen:

  • Eine Ressourcengruppe, die die anderen Ressourcen enthält.
  • Einen Event Hubs-Namespace, ein Event Hub und eine Autorisierungsregel.
  • Ein Konto, eine Datenbank und eine Sammlung für Azure Cosmos DB
  • Eine Funktions-App und ein Speicherkonto, um sie zu hosten.

In den folgenden Abschnitten erfahren Sie, wie Sie diese Ressourcen mit der Azure-Befehlszeilenschnittstelle erstellen.

Festlegen von Umgebungsvariablen

Als nächstes erstellen Sie einige Umgebungsvariablen für die Namen und den Speicherort der zu erstellenden Ressourcen. Verwenden Sie die folgenden Befehle, und ersetzen Sie die <value>-Platzhalter durch Werte Ihrer Wahl. Die Werte müssen den Benennungsregeln und -einschränkungen für Azure-Ressourcen entsprechen. Verwenden Sie für die Variable LOCATION einen der Werte, die durch den Befehl az functionapp list-consumption-locations erzeugt werden.

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>

Im weiteren Verlauf dieses Tutorials werden diese Variablen verwendet. Beachten Sie, dass diese Variablen nur für die Dauer Ihrer aktuellen Azure CLI- oder Cloud Shell-Sitzung bestehen bleiben. Sie müssen diese Befehle erneut ausführen, wenn Sie ein anderes lokales Terminalfenster verwenden oder Ihre Cloud Shell-Sitzung abläuft.

Erstellen einer Ressourcengruppe

Azure verwendet Ressourcengruppen, um alle zugehörigen Ressourcen in Ihrem Konto zu sammeln. Auf diese Weise können Sie sie als Einheit anzeigen und mit einem einzelnen Befehl löschen, wenn Sie mit ihnen fertig sind.

Verwenden Sie den folgenden Befehl, um eine Ressourcengruppe zu erstellen:

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

Erstellen eines Ereignis-Hubs

Als nächstes erstellen Sie mit den folgenden Befehlen einen Azure Event Hubs-Namespace, einen Event Hub und eine Autorisierungsregel:

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

Der Event Hubs-Namespace enthält den eigentlichen Event Hub und dessen Autorisierungsregel. Die Autorisierungsregel ermöglicht es Ihren Funktionen, Nachrichten an den Hub zu senden und auf die entsprechenden Ereignisse zu lauschen. Eine Funktion sendet Nachrichten, die Telemetriedaten darstellen. Eine andere Funktion lauscht auf Ereignisse, analysiert die Ereignisdaten und speichert die Ergebnisse in Azure Cosmos DB.

Erstellen einer Azure Cosmos DB-Instanz

Erstellen Sie anschließend mit den folgenden Befehlen ein Azure Cosmos DB-Konto, eine Datenbank und eine Sammlung:

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'

Der Wert partition-key-path partitioniert Ihre Daten basierend auf dem temperatureStatus-Wert der einzelnen Elemente. Der Partitionsschlüssel ermöglicht es Azure Cosmos DB, die Leistung zu steigern, indem Ihre Daten in verschiedene Teilmengen unterteilt werden, auf die sie unabhängig zugreifen können.

Erstellen eines Speicherkontos und einer Funktions-App

Als nächstes erstellen Sie ein Azure Storage-Konto, das von Azure Functions benötigt wird, und dann erstellen Sie die Funktions-App. Verwenden Sie die folgenden Befehle:

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

Wenn der Befehl az functionapp create Ihre Funktions-App erstellt, erstellt er auch eine Application Insights-Ressource mit demselben Namen. Die Funktions-App wird automatisch mit einer Einstellung namens APPINSIGHTS_INSTRUMENTATIONKEY konfiguriert, die sie mit Application Insights verbindet. Sie können die Anwendungstelemetrie anzeigen, nachdem Sie Ihre Funktionen in Azure bereitgestellt haben, wie später in diesem Tutorial beschrieben.

Konfigurieren Ihrer Funktions-App

Ihre Funktions-App muss auf die anderen Ressourcen zugreifen, um ordnungsgemäß zu funktionieren. In den folgenden Abschnitten erfahren Sie, wie Sie Ihre Funktions-App konfigurieren, dass sie auf Ihrem lokalen Computer ausgeführt werden kann.

Abrufen von Ressourcenverbindungszeichenfolgen

Verwenden Sie die folgenden Befehle, um die Speicher-, Event Hub- und Azure Cosmos DB-Verbindungszeichenfolgen abzurufen und in Umgebungsvariablen zu speichern:

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

Diese Variablen werden auf Werte festgelegt, die über Azure CLI-Befehle abgerufen werden. Jeder Befehl verwendet eine JMESPath-Abfrage, um die Verbindungszeichenfolge aus der zurückgegebenen JSON-Nutzlast zu extrahieren. Die Verbindungszeichenfolgen werden auch mithilfe von echo angezeigt, damit Sie bestätigen können, dass sie erfolgreich abgerufen wurden.

Aktualisieren der Einstellungen Ihrer Funktions-App

Verwenden Sie anschließend den folgenden Befehl, um die Werte der Verbindungszeichenfolge in die App-Einstellungen Ihres Azure Functions-Kontos zu übertragen:

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

Ihre Azure-Ressourcen wurden jetzt erstellt und konfiguriert, um ordnungsgemäß zusammenzuarbeiten.

Erstellen und Testen Ihrer Funktionen

Als nächstes erstellen Sie ein Projekt auf Ihrem lokalen Computer, fügen Java-Code hinzu und testen ihn. Sie verwenden Befehle, die mit dem Azure Functions-Plug-In für Maven und den Azure Functions Core Tools funktionieren. Ihre Funktionen werden lokal ausgeführt, verwenden aber die von Ihnen erstellten cloudbasierten Ressourcen. Nachdem Sie die Funktionen lokal ausgeführt haben, können Sie sie mit Maven in der Cloud bereitstellen und die Ansammlung Ihrer Daten und Analysen beobachten.

Wenn Sie Cloud Shell zur Erstellung Ihrer Ressourcen verwendet haben, werden Sie nicht lokal mit Azure verbunden. Verwenden Sie in diesem Fall den Befehl az login, um den browserbasierten Anmeldevorgang zu starten. Legen Sie dann bei Bedarf das Standardabonnement mit az account set --subscription fest, gefolgt von der Abonnement-ID. Führen Sie abschließend die folgenden Befehle aus, um einige Umgebungsvariablen auf Ihrem lokalen Computer neu zu erstellen. Ersetzen Sie die <value>-Platzhalter durch dieselben Werte, die Sie zuvor verwendet haben.

RESOURCE_GROUP=<value>
FUNCTION_APP=<value>

Erstellen eines lokalen Funktionsprojekts

Verwenden Sie den folgenden Maven-Befehl, um ein Funktionsprojekt zu erstellen und die erforderlichen Abhängigkeiten hinzuzufügen.

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

Dieser Befehl generiert mehrere Dateien in einem telemetry-functions-Ordner:

  • Eine pom.xml-Datei zur Verwendung mit Maven.
  • Eine local.settings.json-Datei zum Speichern von App-Einstellungen für lokale Tests.
  • Eine host.json-Datei, die das Azure Functions Extension Bundle aktiviert, das für die Azure Cosmos DB-Ausgabebindung in Ihrer Datenanalysefunktion benötigt wird.
  • Eine Function.java-Datei, die eine Standardfunktionsimplementierung enthält.
  • Einige Testdateien, die für dieses Tutorial nicht erforderlich sind.

Sie müssen die Testdateien löschen, um Kompilierungsfehler zu vermeiden. Führen Sie die folgenden Befehle aus, um zum neuen Projektordner zu navigieren und den Testordner zu löschen:

cd telemetry-functions
rm -r src/test

Abrufen der Einstellungen Ihrer Funktions-App für die lokale Verwendung

Für lokale Tests benötigt Ihr Funktionsprojekt die Verbindungszeichenfolgen, die Sie Ihrer Funktions-App in Azure zuvor in diesem Tutorial hinzugefügt haben. Verwenden Sie den folgenden Azure Functions Core Tools-Befehl, der alle in der Cloud gespeicherten Einstellungen der Funktions-App abruft und sie zu Ihrer local.settings.json-Datei hinzufügt:

func azure functionapp fetch-app-settings $FUNCTION_APP

Hinzufügen von Java-Code

Öffnen Sie als nächstes die Datei Function.java, und ersetzen Sie den Inhalt durch den folgenden Code.

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

Wie Sie sehen können, enthält diese Datei zwei Funktionen, generateSensorData und processSensorData. Die Funktion generateSensorData simuliert einen Sensor, der Temperatur- und Druckmesswerte an den Event Hub sendet. Ein Trigger mit Timer führt die Funktion alle 10 Sekunden aus, und eine Event Hub-Ausgabebindung sendet den Rückgabewert an den Event Hub.

Wenn der Event Hub die Nachricht empfängt, generiert er ein Ereignis. Die Funktion processSensorData wird ausgeführt, wenn sie das Ereignis empfängt. Anschließend verarbeitet sie die Ereignisdaten und verwendet eine Azure Cosmos DB-Ausgabebindung, um die Ergebnisse an Azure Cosmos DB zu senden.

Die von diesen Funktionen verwendeten Daten werden in einer Klasse namens TelemetryItem gespeichert, die Sie implementieren müssen. Erstellen Sie eine neue Datei namens TelemetryItem.java an demselben Speicherort wie Function.java, und fügen Sie den folgenden Code hinzu:

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

Lokales Ausführen

Sie können die Funktionen jetzt lokal erstellen und ausführen und sehen, dass Daten in Ihrer Azure Cosmos DB angezeigt werden.

Verwenden Sie die folgenden Maven-Befehle, um die Funktionen zu erstellen und auszuführen:

mvn clean package
mvn azure-functions:run

Nach einigen Build- und Startnachrichten wird eine Ausgabe wie im folgenden Beispiel für jede Ausführung der Funktion angezeigt:

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

Sie können dann zum Azure-Portal wechseln und zu Ihrem Azure Cosmos DB-Konto navigieren. Wählen Sie Daten-Explorer, erweitern Sie TelemetryInfo, und wählen Sie dann Elemente aus, um Ihre Daten beim Eintreffen anzuzeigen.

Azure Cosmos DB Data Explorer

Bereitstellen in Azure und Anzeigen der App-Telemetriedaten

Schließlich können Sie Ihre App auch in Azure bereitstellen und überprüfen, ob sie weiterhin wie bei der lokalen Ausführung funktioniert.

Stellen Sie Ihr Projekt mit dem folgenden Befehl in Azure bereit:

mvn azure-functions:deploy

Ihre Funktionen werden jetzt in Azure ausgeführt und sammeln weiterhin Daten in Ihrer Azure Cosmos DB. Sie können Ihre bereitgestellte Funktions-App im Azure-Portal anzeigen und die App-Telemetriedaten über die verbundene Application Insights-Ressource anzeigen, wie in den folgenden Screenshots gezeigt:

Live Metrics Stream:

Application Insights Live Metrics Stream

Leistung:

Application Insights Performance blade

Bereinigen von Ressourcen

Wenn Sie die in diesem Tutorial erstellten Azure-Ressourcen nicht mehr benötigen, können Sie sie mithilfe des folgenden Befehls löschen:

az group delete --name $RESOURCE_GROUP

Nächste Schritte

In diesem Tutorial haben Sie erfahren, wie Sie eine Azure-Funktion erstellen, die Event Hub-Ereignisse verarbeitet und eine Azure Cosmos Datenbankinstanz aktualisiert. Weitere Informationen finden Sie im Java-Entwicklerhandbuch für Azure Functions. Informationen zu den verwendeten Anmerkungen finden Sie in der Referenz zu com.microsoft.azure.functions.annotation.

In diesem Tutorial wurden Umgebungsvariablen und Anwendungseinstellungen verwendet, um Geheimnisse wie Verbindungszeichenfolgen zu speichern. Informationen zum Speichern dieser Geheimnisse in Azure Key Vault finden Sie unter Verwenden von Key Vault-Verweisen für App Service und Azure Functions.

Als nächstes erfahren Sie, wie Sie CI/CD in Azure Pipelines für die automatisierte Bereitstellung verwenden: