Dela via


Självstudie: Skapa en funktion i Java med en Event Hub-utlösare och en Azure Cosmos DB-utdatabindning

Den här självstudien visar hur du använder Azure Functions för att skapa en Java-funktion som analyserar en kontinuerlig ström av temperatur- och tryckdata. Händelsehubbhändelser som representerar sensoravläsningar utlöser funktionen. Funktionen bearbetar händelsedata och lägger sedan till statusposter i en Azure Cosmos DB-instans.

I den här självstudien ska du:

  • Skapa och konfigurera Azure-resurser med hjälp av Azure CLI.
  • Skapa och testa Java-funktioner som interagerar med dessa resurser.
  • Distribuera dina funktioner till Azure och övervaka dem med Application Insights.

Om du inte har en Azure-prenumeration skapar du ett kostnadsfritt Azure-konto innan du börjar.

Förutsättningar

För att slutföra den här självstudien måste du ha följande installerat:

Viktigt!

Miljövariabeln JAVA_HOME måste anges till installationsplatsen för JDK för att slutföra den här självstudien.

Om du föredrar att använda koden för den här självstudien direkt kan du läsa exempellagringsplatsen java-functions-eventhub-cosmosdb .

Skapa Azure-resurser

I den här självstudien behöver du följande resurser:

  • En resursgrupp som ska innehålla de andra resurserna
  • En Event Hubs-namnrymd, händelsehubb och auktoriseringsregel
  • Ett Azure Cosmos DB-konto, en databas och en samling
  • En funktionsapp och ett lagringskonto som ska vara värd för den

I följande avsnitt visas hur du skapar dessa resurser med hjälp av Azure CLI.

Ange miljövariabler

Skapa sedan några miljövariabler för namnen och platsen för de resurser som du skapar. Använd följande kommandon och <value> ersätt platshållarna med de värden du väljer. Värden bör överensstämma med namngivningsreglerna och begränsningarna för Azure-resurser. För variabeln LOCATION använder du ett av de värden som genereras av az functionapp list-consumption-locations kommandot.

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>

Resten av den här självstudien använder dessa variabler. Tänk på att dessa variabler endast finns kvar under den aktuella Azure CLI- eller Cloud Shell-sessionen. Du måste köra dessa kommandon igen om du använder ett annat lokalt terminalfönster eller om tidsgränsen för Cloud Shell-sessionen uppnås.

Skapa en resursgrupp

Azure använder resursgrupper för att samla in alla relaterade resurser i ditt konto. På så sätt kan du visa dem som en enhet och ta bort dem med ett enda kommando när du är klar med dem.

Använd följande kommando för att skapa en resursgrupp:

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

Skapa en händelsehubb

Skapa sedan en Azure Event Hubs-namnrymd, händelsehubb och auktoriseringsregel med hjälp av följande kommandon:

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

Event Hubs-namnområdet innehåller den faktiska händelsehubben och dess auktoriseringsregel. Auktoriseringsregeln gör att dina funktioner kan skicka meddelanden till hubben och lyssna efter motsvarande händelser. En funktion skickar meddelanden som representerar telemetridata. En annan funktion lyssnar efter händelser, analyserar händelsedata och lagrar resultaten i Azure Cosmos DB.

Skapa en Azure Cosmos DB

Skapa sedan ett Azure Cosmos DB-konto, en databas och en samling med följande kommandon:

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'

Värdet partition-key-path partitioner dina data baserat på värdet för temperatureStatus varje objekt. Med partitionsnyckeln kan Azure Cosmos DB öka prestandan genom att dela upp dina data i distinkta delmängder som den kan komma åt oberoende av varandra.

Skapa ett lagringskonto och en funktionsapp

Skapa sedan ett Azure Storage-konto som krävs av Azure Functions och skapa sedan funktionsappen. Använd följande kommandon:

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

az functionapp create När kommandot skapar din funktionsapp skapas även en Application Insights-resurs med samma namn. Funktionsappen konfigureras automatiskt med en inställning med namnet APPINSIGHTS_INSTRUMENTATIONKEY som ansluter den till Application Insights. Du kan visa apptelemetri när du har distribuerat dina funktioner till Azure, enligt beskrivningen senare i den här självstudien.

Konfigurera funktionsappen

Funktionsappen måste komma åt de andra resurserna för att fungera korrekt. I följande avsnitt visas hur du konfigurerar funktionsappen så att den kan köras på den lokala datorn.

Hämta resurs anslutningssträng

Använd följande kommandon för att hämta lagring, händelsehubb och Azure Cosmos DB-anslutningssträng och spara dem i miljövariabler:

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

Dessa variabler är inställda på värden som hämtats från Azure CLI-kommandon. Varje kommando använder en JMESPath-fråga för att extrahera anslutningssträng från JSON-nyttolasten som returneras. Anslutningssträng visas också med så echo att du kan bekräfta att de har hämtats.

Uppdatera inställningarna för funktionsappen

Använd sedan följande kommando för att överföra anslutningssträng värden till appinställningar i ditt Azure Functions-konto:

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

Dina Azure-resurser har nu skapats och konfigurerats för att fungera korrekt tillsammans.

Skapa och testa dina funktioner

Därefter skapar du ett projekt på den lokala datorn, lägger till Java-kod och testar det. Du använder kommandon som fungerar med Azure Functions-plugin-programmet för Maven och Azure Functions Core Tools. Dina funktioner körs lokalt, men använder de molnbaserade resurser som du har skapat. När du har fått funktionerna att fungera lokalt kan du använda Maven för att distribuera dem till molnet och se dina data och analyser ackumuleras.

Om du använde Cloud Shell för att skapa dina resurser kommer du inte att vara ansluten till Azure lokalt. I det här fallet använder du az login kommandot för att starta den webbläsarbaserade inloggningsprocessen. Ange sedan standardprenumerationen med az account set --subscription följt av prenumerations-ID:t om det behövs. Kör slutligen följande kommandon för att återskapa vissa miljövariabler på den lokala datorn. <value> Ersätt platshållarna med samma värden som du använde tidigare.

RESOURCE_GROUP=<value>
FUNCTION_APP=<value>

Skapa ett lokalt funktionsprojekt

Använd följande Maven-kommando för att skapa ett funktionsprojekt och lägga till nödvändiga beroenden.

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

Det här kommandot genererar flera filer i en telemetry-functions mapp:

  • En pom.xml fil som ska användas med Maven
  • En local.settings.json fil som ska innehålla appinställningar för lokal testning
  • En host.json fil som aktiverar Azure Functions-tilläggspaketet som krävs för Azure Cosmos DB-utdatabindning i din dataanalysfunktion
  • En Function.java fil som innehåller en standardfunktionsimplementering
  • Några testfiler som den här självstudien inte behöver

För att undvika kompileringsfel måste du ta bort testfilerna. Kör följande kommandon för att navigera till den nya projektmappen och ta bort testmappen:

cd telemetry-functions
rm -r src/test

Hämta inställningarna för funktionsappen för lokal användning

För lokal testning behöver funktionsprojektet de anslutningssträng som du lade till i funktionsappen i Azure tidigare i den här självstudien. Använd följande Azure Functions Core Tools-kommando, som hämtar alla inställningar för funktionsappen som lagras i molnet och lägger till dem i filen local.settings.json :

func azure functionapp fetch-app-settings $FUNCTION_APP

Lägg till Java-kod

Öppna Function.java sedan filen och ersätt innehållet med följande kod.

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

Som du ser innehåller den här filen två funktioner och generateSensorData processSensorData. Funktionen generateSensorData simulerar en sensor som skickar temperatur- och tryckavläsningar till händelsehubben. En timerutlösare kör funktionen var 10:e sekund och en utdatabindning för händelsehubben skickar returvärdet till händelsehubben.

När händelsehubben tar emot meddelandet genereras en händelse. Funktionen processSensorData körs när den tar emot händelsen. Den bearbetar sedan händelsedata och använder en Azure Cosmos DB-utdatabindning för att skicka resultaten till Azure Cosmos DB.

De data som används av dessa funktioner lagras med hjälp av en klass med namnet TelemetryItem, som du måste implementera. Skapa en ny fil med TelemetryItem.java namnet på samma plats som Function.java och lägg till följande kod:

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

Kör lokalt

Nu kan du skapa och köra funktionerna lokalt och se data visas i Azure Cosmos DB.

Använd följande Maven-kommandon för att skapa och köra funktionerna:

mvn clean package
mvn azure-functions:run

Efter några kompilerings- och startmeddelanden visas utdata som liknar följande exempel för varje gång funktionerna körs:

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

Du kan sedan gå till Azure-portalen och gå till ditt Azure Cosmos DB-konto. Välj Datautforskaren, expandera TelemetryInfo och välj sedan Objekt för att visa dina data när de tas emot.

Azure Cosmos DB Data Explorer

Distribuera till Azure och visa apptelemetri

Slutligen kan du distribuera din app till Azure och kontrollera att den fortsätter att fungera på samma sätt som den gjorde lokalt.

Distribuera projektet till Azure med följande kommando:

mvn azure-functions:deploy

Funktionerna körs nu i Azure och fortsätter att samla in data i Azure Cosmos DB. Du kan visa din distribuerade funktionsapp i Azure-portalen och visa apptelemetri via den anslutna Application Insights-resursen enligt följande skärmbilder:

Live Metrics Stream:

Application Insights Live Metrics Stream

Prestanda:

Application Insights Performance blade

Rensa resurser

När du är klar med de Azure-resurser du har skapat i den här självstudien kan du ta bort dem med hjälp av följande kommando:

az group delete --name $RESOURCE_GROUP

Nästa steg

I den här självstudien har du lärt dig hur du skapar en Azure-funktion som hanterar Event Hub-händelser och uppdaterar en Azure Cosmos DB-instans. Mer information finns i utvecklarguiden för Azure Functions Java. Information om de anteckningar som används finns i referensen com.microsoft.azure.functions.annotation .

I den här självstudien används miljövariabler och programinställningar för att lagra hemligheter som anslutningssträng. Information om hur du lagrar dessa hemligheter i Azure Key Vault finns i Använda Key Vault-referenser för App Service och Azure Functions.

Lär dig sedan hur du använder Azure Pipelines CI/CD för automatiserad distribution: