背景
IoT機器から送信されるさまざまなファイルをBlob Storageに取り込み、Azure FunctionsのBlob Triggerを用いて処理を行っています。システムをリリースした数年前は数分以内に処理が完了しており1、システムの特性上、特に問題はありませんでした。
しかしながら、ここ1年ほどでファイル数が大幅に増え2、取り込みの遅延が数時間から場合によっては1日以上に及び、データを利用しているシステムに影響が出始めていました。
結論
以下の記事を参考にして、Event Gridを経由してBlob Triggerを起動することで、ほぼ遅延がなくなりました。
-
チュートリアル: イベントサブスクリプションを使用してBLOBコンテナーでAzure Functionsをトリガーする
- Event Gridを有効化
- Storage Accountのイベントをサブスクライブできるよう設定する
-
Microsoft.Azure.Functions.Worker.Extensions.Storage.Blobs
のバージョンを5.x以上にする - Blob Trigger属性のパラメータに
source = BlobTriggerSource.EventGrid
を追加する
-
Azure Event Gridを使用してBLOBストレージイベントをWebエンドポイントにルーティングする (Azure portal)
- 本番環境でデバッグする場合(フィルタ設定をテストする場合など)は、ページ内の「Deploy to Azure」ボタンを使ってデプロイできるアプリケーションが便利です
原因
Blob Triggerは、ポーリングと待ち時間に記載されているように、10,000ファイルごとにポーリングを実施し、変化を検出しています。つまり、保存されているファイルが多くなると、それだけ遅延が増加することになります。
Blob Triggerの設定はhost.json
に記載することができます。そこで、ポーリング間隔を短くしたり、スキャンするファイル数を変更できないか調べましたが、host.json 設定にある通り、これらの設定を変更することはできないようでした。
実際の作業
前提としてFunctions、Blob Storageは作成済みです。そのため、Event Gridの有効化、Blob Storageのイベント設定、Functionsのパラメータ追加を実施しました。
Event Gridの有効化
最初の時点ではEvent Gridが有効化されていないので、Microsoft.EventGrid
を検索し、三点リーダから「登録」をクリックします。
1分ほどすると設定が完了し、状態がregisteredに変わります。
これで準備はOKです。
Functionsのパラメータ追加
Functionsの設定を行う前にMicrosoft.Azure.Functions.Worker.Extensions.Storage.Blobs
のバージョンを5.x以上にします。
次にBlob Trigger属性のパラメータにSource = BlobTriggerSource.EventGrid
を追加します。
[FunctionName("LogToDatabase")]
public void Run(
[BlobTrigger(
"logs/{id}/{year}-{month}-{day}-{hour}-{minute}-{second}.txt",
+ Source = BlobTriggerSource.EventGrid,
Connection = "LogConnectionString"
)] Stream myBlob,
string id,
int year,
int month,
int day,
int hour,
int minute,
int second,
int blobTrigger,
ILogger log)
{
}
Azure Event Grid Viewerのデプロイ
Azure-Samples/azure-event-grid-viewer を利用すると、Event Gridが発行するイベントを簡単に確認できます。リソースもApp ServiceプランとApp Serviceしかデプロイしないので、後片付けも簡単です。
Blob Storageの設定
ストレージアカウント左メニューの「イベント」でイベントの発行を設定できます。
「+イベントサブスクリプション」から、イベントを作成する。
エンドポイント
デバッグ環境
エンドポイントを先ほど作成したAzure Event Grid ViewerのURL+/api/updates
とします。
本番環境
https://<FUNCTION_APP_NAME>.azurewebsites.net/runtime/webhooks/blobs?functionName=BlobTriggerEventGrid&code=<BLOB_EXTENSION_KEY>
この例で、 を関数アプリの名前に置き換え、 をポータルから取得した値に置き換えます。 関数に別の名前を使用した場合は、必要に応じて functionName クエリ文字列を変更する必要もあります。
フィルター
Functionsが1つだけであったとしても、Triggerのフォーマットと異なる形式を送ってしまうとエラーになってしまうため、正しく指定します。デバッグ環境で正しく送信されることを確認してからエンドポイントを本番環境に変更することをお勧めします3。
Azure Event Grid Viewerでの確認
ストレージアカウントにファイルをアップロードすると、Azure Event Grid Viewerにイベントが発行され、データが確認できます。
コンテナを指定したい場合は「次で始まるサブジェクト」に /blobServices/default/containers/<container name>
を指定しておくといいです。高度なフィルターでも様々な設定ができるので便利でした。
雑感
FunctionsのBlob Triggerを改善しないといけないと思いつつ、放置してしまっていました。今回、Event Grid経由にしたことでシステムの遅延を大幅に改善できてよかったと思います。