Azure Event GridでCloudEventsを使う

このエントリは2020/09/05現在の情報に基づいています。将来の機能追加や変更により記載内容との乖離が発生する可能性があります。

CloudEventsとは

CNCF (Cloud Native Computing Foundation) が策定する、イベントデータを標準的な方法で表記し、サービスやプラットフォームなどを超えて、イベントの定義や通知を容易にするための仕様。イベント発行者がこの仕様に従ってイベントを送出してくれれば、受信側も仕様に基づいていれば自社他社製品やサービスを問わずにイベントを解釈、処理できる、というもの。

CloudEvents
https://cloudevents.io/

Azureでの対応状況(2020/09/05現在)

以下のドキュメントにも記載の通り、Azure Event Gridにおいて、システムイベントやカスタムイベントの伝播のためにCloudEventsを利用できる。スキーマはCloudEvents 1.0。

また、FunctionsでもCloudEvents 1.0スキーマのイベントを処理できるが、ネイティブのバインド、つまりEvent Gridトリガーではなく、HTTPトリガーを使う必要がある。

Event Grid に CloudEvents v1.0 スキーマを使用する
Use CloudEvents v1.0 schema with Event Grid
https://docs.microsoft.com/azure/event-grid/cloudevents-schema

動作確認

Event GridでのCloudEventsスキーマの利用

CLI、PowerShell、ポータルのいずれからも構成できる。入力側ではTopicの作成時にスキーマを指定する。以下はCLIの例。CLIの場合、extensionを追加しておく必要がある。PowerShellの場合はAzureRM.EventGrid モジュールが必要。何れも上記のURLに説明がある。

# install the extension
az extension add --name eventgrid

# update the extension
az extension update -n eventgrid

# Environment Variables
ResourceGroup=logico-eventgrid
TopicName=logico-topic
Location=japaneast

az group create -n $ResourceGroup -l $Location

# Create topic (CloudEvents schema is used for an input schema)
az eventgrid topic create \
  --name $TopicName \
  -l $Location \
  -g $ResourceGroup \
  --input-schema cloudeventschemav1_0

出力側はイベントサブスクリプション作成時にスキーマを指定。

# Environment Variables
EventSubscriptionName=logico-subscribe

topicId=$(az eventgrid topic show -n $TopicName -g $ResourceGroup --query id -o tsv)
endpointUrl=$(az eventgrid topic show -n $TopicName -g $ResourceGroup --query endpoint -o
tsv)

# Create event subscription  (CloudEvents schema is used for an output schema)
az eventgrid event-subscription create \
  -n $EventSubscriptionName \
  --source-resource-id $topicId \
  --endpoint $endpointUrl \
  --event-delivery-schema cloudeventschemav1_0

ドキュメントの通り、CloudEventsスキーマは入出力で利用できるが、CloudEventsスキーマのイベントをEvent Gridの形式に変換はできない。逆にEvent Grid形式をCloudEventsスキーマに変換することは可能。

CloudEventsはシステムイベントやカスタムイベントに利用できる。

From ➜ ToCloudEventsEvent Grid
CloudEvents×
Event Grid

Blob Storageのイベント(ファイル削除)をEvent GridスキーマとCloudEvents 1.0スキーマで送出した場合を比較してみる。

Event Gridの場合
{
  "topic": "/subscriptions/7xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx8/resourceGroups/logico-eventgrid/providers/Microsoft.Storage/storageAccounts/logicojpstorage",
  "subject": "/blobServices/default/containers/logico-blob/blobs/JMS_01.png",
  "eventType": "Microsoft.Storage.BlobDeleted",
  "id": "73981098-401e-0022-3460-83ee0506c13b",
  "data": {
    "api": "DeleteBlob",
    "clientRequestId": "74872587-76d8-43b6-43b0-6180651057ae",
    "requestId": "73981098-401e-0022-3460-83ee05000000",
    "eTag": "0x8D851776D224F51",
    "contentType": "image/png",
    "contentLength": 161109,
    "blobType": "BlockBlob",
    "url": "https://logicojpstorage.blob.core.windows.net/logico-blob/JMS_01.png",
    "sequencer": "000000000000000000000000000071B4000000000002e6a6",
    "storageDiagnostics": {
      "batchId": "50a8f338-d006-002c-0060-83020e000000"
    }
  },
  "dataVersion": "",
  "metadataVersion": "1",
  "eventTime": "2020-09-05T08:41:04.7038473Z"
}
CloudEvents 1.0の場合
{
  "id": "73981098-401e-0022-3460-83ee0506c13b",
  "source": "/subscriptions/7xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx8/resourceGroups/logico-eventgrid/providers/Microsoft.Storage/storageAccounts/logicojpstorage",
  "specversion": "1.0",
  "type": "Microsoft.Storage.BlobDeleted",
  "dataschema": "#",
  "subject": "/blobServices/default/containers/logico-blob/blobs/JMS_01.png",
  "time": "2020-09-05T08:41:04.7038473Z",
  "data": {
    "api": "DeleteBlob",
    "clientRequestId": "74872587-76d8-43b6-43b0-6180651057ae",
    "requestId": "73981098-401e-0022-3460-83ee05000000",
    "eTag": "0x8D851776D224F51",
    "contentType": "image/png",
    "contentLength": 161109,
    "blobType": "BlockBlob",
    "url": "https://logicojpstorage.blob.core.windows.net/logico-blob/JMS_01.png",
    "sequencer": "000000000000000000000000000071B4000000000002e6a6",
    "storageDiagnostics": {
      "batchId": "50a8f338-d006-002c-0060-83020e000000"
    }
  }
}

FunctionsでのCloudEventsの取り扱い

前述の通りEvent Gridトリガーは使えないため、HTTPトリガーを使う必要があるが、注意すべきは、イベントサブスクライブのためのエンドポイントの指定。Azure Functionsではなく、Webhookを使わなければならない。Functionsを選択すると、Event Gridトリガーを要求するためである。エンドポイントはFunctionsのURLを指定する。形式は、

https://<App Name>.azurewebsites.net/api/<Function Name>

で、以下のコード例では

https://eventfunc4logico.azurewebsites.net/api/CloudEvents

を指定している。

ドキュメントにはC#とJavaScriptの例しかないので、例によってJavaで書いてみる。

MavenでArcheTypeを作成して…

mvn archetype:generate \
-DarchetypeGroupId=com.microsoft.azure \
-DarchetypeArtifactId=azure-functions-archetype \
-DappName=EventFunc4logico \
-DappRegion=$Location \
-DresourceGroup=$ResourceGroup \
-DgroupId=io.logico.group \
-DartifactId=EventFunc4logico \
-Dpackage=com.logico \
-DinteractiveMode=false

生成されたpom.xmlを編集し、使用するJavaバージョンは11、OSはLinuxにしておく(これは完全な好み)。このあたりは以下に記載している。

Azure Functions v3 で Java 11 をサポート
https://logico-jp.io/2020/07/22/azure-functions-v3-supports-java-11/

ドキュメントにある通り、OPTIONSメソッドでの挙動を追加しておく。あとは通常のHTTPトリガーのFunctionsと何も違いはない。受信メッセージの内容を把握できるよう、ログ出力のコードを入れてある。

package com.logico;

import com.microsoft.azure.functions.ExecutionContext;
import com.microsoft.azure.functions.HttpMethod;
import com.microsoft.azure.functions.HttpRequestMessage;
import com.microsoft.azure.functions.HttpResponseMessage;
import com.microsoft.azure.functions.HttpStatus;
import com.microsoft.azure.functions.annotation.AuthorizationLevel;
import com.microsoft.azure.functions.annotation.FunctionName;
import com.microsoft.azure.functions.annotation.HttpTrigger;
import java.util.Optional;

public class Function {
    @FunctionName("CloudEvents")
    public HttpResponseMessage run(
            @HttpTrigger(
                name = "req",
                methods = {HttpMethod.GET, HttpMethod.POST, HttpMethod.OPTIONS},
                authLevel = AuthorizationLevel.ANONYMOUS)
                HttpRequestMessage<Optional<String>> request,
            final ExecutionContext context) {
        context.getLogger().info("Java HTTP trigger processed a request.");

        if(request.getHttpMethod().equals(HttpMethod.OPTIONS)) {
            // If the request is for subscription validation, send back the validation code
            context.getLogger().info("OPTIONS");
            return request.createResponseBuilder(HttpStatus.OK)
                    .header("Webhook-Allowed-Origin","eventgrid.azure.net")
                    .build();
        }

        context.getLogger().info("Other CloudEvents");
        context.getLogger().info(request.getBody().toString());

        return request.createResponseBuilder(HttpStatus.OK).build();
    }
}

で、実際にBlobからファイルを削除したイベントを受け取ったらこんな感じ。

JSONだけ取り出すと

{
    "id": "cef3ce5f-401e-000b-569b-8398470699ee",
    "source": "/subscriptions/7xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx8/resourceGroups/logico-eventgrid/providers/Microsoft.Storage/storageAccounts/logicojpstorage",
    "specversion": "1.0",
    "type": "Microsoft.Storage.BlobDeleted",
    "dataschema": "#",
    "subject": "/blobServices/default/containers/logico-blob/blobs/JMS_01.png",
    "time": "2020-09-05T15:42:52.6443786Z",
    "data": {
        "api": "DeleteBlob",
        "clientRequestId": "1cc549e5-e838-4908-546b-9c0659117727",
        "requestId": "cef3ce5f-401e-000b-569b-839847000000",
        "eTag": "0x8D851B259DA790A",
        "contentType": "image/png",
        "contentLength": 161109,
        "blobType": "BlockBlob",
        "url": "https://logicojpstorage.blob.core.windows.net/logico-blob/JMS_01.png",
        "sequencer": "000000000000000000000000000071B40000000000f10049",
        "storageDiagnostics": {
            "batchId": "51c42c1b-d006-002c-009b-83020e000000"
        }
    }
}

ということで、問題なくイベントを受信できることは確認できた。

コメントを残す

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください