Ćwiczenie — tworzenie funkcji platformy Azure w celu symulowania danych telemetrycznych

Ukończone

W naszym przykładzie używamy określania źródła zdarzeń. Skompilujmy funkcję, która symuluje dane telemetryczne i wyślemy ją do centrum zdarzeń. Później inna funkcja może nasłuchiwać tego zdarzenia i przetwarzać go i przechowywać w bazie danych utworzonej za pomocą usługi Azure Cosmos DB.

Wizualizacja sourcingu zdarzeń przy zakupie kawy w kawiarni.

Przygotowywanie środowiska

Zdefiniujmy niektóre zmienne środowiskowe, aby zachować następujące polecenia tak krótkie i zrozumiałe, jak to możliwe. Zdefiniuj symbole zastępcze <value>, a następnie wklej i uruchom następujące polecenia w terminalu lub w narzędziu wiersza poleceń.

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>

Notatka

Aby ustawić zmienną LOCATION, możesz sprawdzić polecenie az functionapp list-consumption-locations i użyć najbliższej lokalizacji.

Tworzenie wymaganych składników

Aprowizowanie zasobów na platformie Azure zajmuje trochę czasu. Zacznijmy od utworzenia składnika tak szybko, jak to możliwe, aby uniknąć długich oczekiwań później.

Tworzenie grupy zasobów

Zawsze dobrym pomysłem jest powiązanie wszystkich zasobów szkolenia, weryfikacji koncepcji lub prototypu w jednej grupie zasobów. Dzięki temu można wygodnie wyczyścić wszystkie używane usługi za pomocą jednego polecenia. Aby utworzyć grupę zasobów w określonej lokalizacji, uruchom następujące polecenie w terminalu:

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

Tworzenie i konfigurowanie centrum zdarzeń

W przypadku centrum zdarzeń należy określić przestrzeń nazw, której ma nasłuchiwać. Ponadto należy skonfigurować regułę autoryzacji dla Listen i 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

Kompilowanie, konfigurowanie i wdrażanie funkcji platformy Azure

Aby ten przykład był jak najbardziej realistyczny, utwórz funkcję platformy Azure i symuluj dane telemetryczne. Możesz również powiązać urządzenie IoT z funkcją platformy Azure, która następnie będzie pobierać rzeczywiste dane. Ponieważ ta funkcja jest odpowiedzialna za tworzenie zdarzeń, dodajmy flagę p lub -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

Notatka

Używaj funkcji w wersji 4, ponieważ wersje 2 i 3 zostały wycofane w grudniu 2022 r.

Gdy polecenie az functionapp create tworzy aplikację funkcji, tworzy również zasób usługi Application Insights o tej samej nazwie. Ten zasób jest używany później do monitorowania.

Aby pobrać parametry połączenia dla konta magazynowego i centrum zdarzeń, użyj następujących poleceń, aby zapisać je w zmiennych środowiskowych, a następnie wyświetlić je za pomocą polecenia echo.

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

Aby przechowywać parametry połączenia w ustawieniach aplikacji konta funkcji platformy Azure, uruchom następujące polecenie w terminalu:

az functionapp config appsettings set \
    --resource-group $RESOURCE_GROUP \
    --name $FUNCTION_APP"-p" \
    --settings \
        AzureWebJobsStorage=$AZURE_WEB_JOBS_STORAGE \
        EventHubConnectionString=$EVENT_HUB_CONNECTION_STRING

Teraz centrum zdarzeń i funkcja platformy Azure są utworzone i skonfigurowane do prawidłowej współpracy.

Następnie utwórz projekt funkcji lokalnych za pomocą narzędzia 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

To polecenie generuje kilka plików w folderze telemetry-functions-producer:

  • Plik kompilacji pom.xml ze wstępnie zdefiniowanymi zależnościami platformy Azure.
  • Plik local.settings.json do przechowywania ustawień aplikacji na potrzeby lokalnego wdrażania i testowania ręcznego.
  • Plik host.json, który umożliwia pakiet rozszerzeń usługi Azure Functions.
  • Plik Function.java zawierający domyślną funkcję wyzwalacza HTTP.
  • Kilka plików testowych, których nie używa ten moduł Learn.

Nie dotykamy plików testowych w tym module Learn, więc możesz je usunąć.

cd telemetry-functions-producer
rm -r src/test

W przypadku wykonywania lokalnego ustawienia aplikacji należy pobrać i przechowywać w pliku local.settings.json. Możesz to zrobić automatycznie, uruchamiając polecenie fetch-app-settings.

func azure functionapp fetch-app-settings $FUNCTION_APP"-p"

Następnie otwórz plik Function.java i zastąp zawartość następującym kodem:

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

Funkcja generateSensorData symuluje czujnik, który wysyła odczyty temperatury i ciśnienia do centrum zdarzeń. Wyzwalacz czasomierza uruchamia funkcję co 10 sekund, a powiązanie wyjściowe Centrum Zdarzeń wysyła wartość zwracaną do Centrum Zdarzeń.

Gdy centrum zdarzeń odbiera komunikat, generuje zdarzenie.

Dane używane przez tę funkcję są przechowywane przy użyciu klasy o nazwie TelemetryItem, którą należy zaimplementować. Utwórz nowy plik o nazwie TelemetryItem.java w tej samej lokalizacji co Function.java i dodaj następujący kod:

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

Uruchamianie lokalne

Po uruchomieniu funkcji platformy Azure lokalnie są one już przesyłane strumieniowo na całym świecie! Ponadto możesz przejrzeć je w witrynie Azure Portal.

mvn clean package
mvn azure-functions:run

Po wykonaniu niektórych komunikatów kompilacji i uruchamiania zobaczysz dane wyjściowe podobne do następujących przykładów po każdym uruchomieniu funkcji:

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

Uwaga

Przed wdrożeniem i uruchomieniem funkcji w chmurze platformy Azure możesz wysyłać zdarzenia z komputera lokalnego na całym świecie. Jest to bardzo przydatne w przypadku programowania, debugowania i testowania lokalnego.

Wdrażanie na platformie Azure

Wyzwól wdrożenie na platformie Azure, uruchamiając polecenie mvn azure-functions:deploy i kontynuuj.

mvn azure-functions:deploy