演習 - テレメトリ データをシミュレートする Azure 関数を構築する

完了

この例では、イベント ソーシングを使用します。 テレメトリ データをシミュレートする関数を構築し、イベント ハブに送信してみましょう。 後で、別の関数がこのイベントをリッスンして処理し、Azure Cosmos DB で作成されたデータベースに格納できます。

コーヒー ショップでコーヒーを購入するためのイベント ソーシングの視覚化。

環境を準備する

次のコマンドをできるだけ短く理解できるように、いくつかの環境変数を定義しましょう。 <value>プレースホルダーを定義し、ターミナルまたはコマンドライン ツールで次のコマンドを貼り付けて実行します。

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>

LOCATION 変数を設定するには、 az functionapp list-consumption-locations コマンドを確認し、最も近い場所を使用します。

必要なコンポーネントを作成する

Azure でのリソースのプロビジョニングには時間がかかります。 後で長い待ち時間を避けるために、できるだけ早くコンポーネントの作成から始めましょう。

リソース グループを作成する

トレーニング、概念実証、またはプロトタイプのすべてのリソースを 1 つのリソース グループにバインドすることをお勧めします。 こうすることで、使用されているすべてのサービスを 1 つのコマンドで簡単にクリーンアップできます。 指定した場所にリソース グループを作成するには、ターミナルで次のコマンドを実行します。

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

イベント ハブを作成および構成する

イベント ハブの場合は、リッスンする名前空間を指定する必要があります。 また、 Listen して 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

Azure 関数をビルド、構成、デプロイする

この例を可能な限り現実的にするには、Azure 関数を作成し、テレメトリ データをシミュレートします。 IoT デバイスを Azure 関数にバインドして、実際のデータを取得することもできます。 この関数はイベント生成関数であるため、 p フラグまたは -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

2022 年 12 月に非推奨となった 2 と 3 として functions-version 4 を使用します。

az functionapp create コマンドによって関数アプリケーションが作成されると、同じ名前の Application Insights リソースも作成されます。 そのリソースは後で監視に使用します。

ストレージ アカウントとイベント ハブの接続文字列を取得するには、次のコマンドを使用して環境変数に保存し、 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

接続文字列を Azure 関数アカウントのアプリケーション設定に格納するには、ターミナルで次のコマンドを実行します。

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

これで、Azure リソース イベント ハブと Azure 関数が作成され、正常に連携するように構成されます。

次に、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

このコマンドによって、telemetry-functions-producer フォルダー内にいくつかのファイルが生成されます。

  • 定義済みの Azure 依存関係を持つ pom.xml ビルド ファイル。
  • ローカル展開と手動テスト用のアプリケーション設定を保持する local.settings.json ファイル。
  • Azure Functions 拡張機能バンドルを有効にする host.json ファイル。
  • 既定の HTTP トリガー関数を含む Function.java ファイル。
  • この Learn モジュールで使用されていないいくつかのテスト ファイル。

この Learn モジュールのテスト ファイルには触れないので、自由に削除してください。

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

ローカルで実行するには、アプリケーション設定を取得し、 local.settings.json ファイルに格納する必要があります。 fetch-app-settings コマンドを実行すると、これを自動的に実行できます。

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

次に、 Function.java ファイルを開き、内容を次のコードに置き換えます。

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

generateSensorData 関数を使うと、イベント ハブに気温と気圧の測定値を送信するセンサーをシミュレートできます。 タイマー トリガーによって 10 秒ごとに関数が実行され、イベント ハブの出力バインドから戻り値がイベント ハブに送信されます。

イベント ハブでは、メッセージを受け取ると、イベントが生成されます。

この関数で使用されるデータは、TelemetryItem というクラスを使用して格納されます。これを実装する必要があります。 Function.javaと同じ場所に TelemetryItem.java という名前の新しいファイルを作成し、次のコードを追加します。

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

ローカルで実行する

Azure 関数をローカルで実行すると、既に世界中にストリーミングされています。 また、Azure portal で確認することもできます。

mvn clean package
mvn azure-functions:run

いくつかのビルドおよび起動メッセージの後、関数が実行されるたびに次の例のような出力が表示されます。

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

Azure クラウドで関数をデプロイして実行する前に、世界中のローカル コンピューターからイベントを送信できます。 これは、開発、デバッグ、ローカル テストに非常に役立ちます。

Azure にデプロイする

mvn azure-functions:deploy コマンドを実行して Azure へのデプロイをトリガーし、続行します。

mvn azure-functions:deploy