
先日、社内の Hack イベントに参加しました。
その中で、課題シナリオの一部に
‐ Storage Account の Blob コンテナーへの保存をトリガーに、Azure Functions の関数で処理を実行する
という要件があり、改めていくつかの方式を調べて比較したので、まとめてみました。
サポートされているトリガー
現在プレビューも含めて、Blob の保存をトリガーとして Azure Functions は以下の 3 つです。
- Blob トリガー
- Event Grid トリガー
- Event Grid Blob トリガー
それぞれについて簡単な説明と Pros./Cons. をまとめてみました。
結論から見たい人はこちら。
Blob トリガー
最初は Blob トリガーです。
まず最初に試すのはこれではないでしょうか。名前もわかりやすいですし。
仕組み
Blob トリガーは、Azure Functions のホスト プロセスから対象のコンテナーに対して定期的にスキャンを実行し、新規に保存されたファイルがあればトリガーする、という仕組みで実現しています。
Pros.
Blob コンテンツの取得がめちゃくちゃ楽です。
例えば JavaScript の場合、function.json の中で以下のように Blob トリガーを設定すると、context.bindings.myBlob という変数でコンテンツの本体にアクセスできます。
{ "bindings": [ { "name": "myBlob", "type": "blobTrigger", "direction": "in", "path": "samples-workitems/{name}", // `<コンテナー名>/<Blob 名>` の書式が必要 "connection":"MyStorageAccountAppSetting" } ] }
Cons.
仕組みのところに書いたように、このトリガーは Azure Functions 側からの対象のコンテナーに新規の Blob がないかスキャンしています。
なので、コンテナー内のファイルの数が膨大になると、コンテナーのスキャンに時間がかかるので、その結果、Blob の保存とトリガーのタイミングに差が出ることがあります。
この時間差を回避するため、Blob コンテナーのログ ファイルのスキャンで Blob 作成のログで新規の Blob 作成もチェックもしていますが、ストレージ ログの記録がベストエフォートのため、全てカバーできるわけではありません。
また関数実行は 1 回だけなので、関数内部で例外等が発生し失敗した場合もリトライは行われません。
リトライ処理をしたければ、関数内の例外処理の中で対象 Blob の情報を Queue に退避させて Queue トリガーで再処理、といった処理を自前で実装する必要があります。
あと Blob トリガーの仕様として、必ず対象の Blob コンテナーを一つだけ決める必要があります。
その為、path プロパティの値は必ず <コンテナー名>/<Blob パス> となります。
| コンテンツ取得 | リアルタイム性 | 信頼性 | |
|---|---|---|---|
| Blob トリガー | 〇 | △ ※ファイル数に依存 |
〇 |
Event Grid トリガー
次に Event Grid トリガーです。
仕組み
これは Storage Account をイベント ソース、Azure Functions をイベント ハンドラーとして、Storage Account で発生したイベントを Azure Functions にリアルタイムに送信する仕組みです。
ちなみに、Azure Functions の Event Grid トリガー関数は、/runtime/webhooks/eventgrid?functionName=<関数名> という特殊な URL を持った HTTP トリガー関数なので、このイベントの送信は、その URL に対する Web Hook を実行する形で実装されています。
Storage Account 側の設定は下記ドキュメントのように、[イベント] ブレードからイベント サブスクリプションを作成するだけです。
エンドポイントについては、Web Hook でも Azure Functions に接続できますが、[Azure 関数] を選べば関数を自動的にピックアップしてくれるので楽チンです。
トリガー バインディングの設定はこれだけです。
{ "bindings": [ { "type": "eventGridTrigger", "name": "eventGridEvent", "direction": "in" } ] }
Pros.
イベント ソース側でイベントが発生するとすぐに Web Hook が実行され関数がトリガーされるので、実行は常にリアルタイムです。
また関数側でエラーが発生した場合など、正しい応答が返らなかった場合、Event Grid が自動的にリトライをしてくれるので、信頼性も高いです。
Cons.
一方で、このトリガーだけで取れるのは、Blob に関するイベントだけでは Blob のコンテンツそのものは取れません。
| コンテンツ取得 | リアルタイム性 | 信頼性 | |
|---|---|---|---|
| Event Grid トリガー | × | 〇 | 〇 |
Event Grid Blob トリガー
Blob トリガーの簡単なコンテンツ ハンドリングと Event Grid トリガーのリアルタイム性をいいとこどりしたトリガーです。
仕組み
Event Grid トリガー同様、Event Grid を介して、特殊な URL /runtime/webhooks/blobs?functionName=<関数名> に対して Web Hook が実行されます。
通常の Blob トリガーとの違いは、Azure Functions 側はトリガー用のバインディング設定に "source": "EventGrid" という設定を追加することと、Storage Account 側は Event Grid トリガー同様、[イベント] ブレードからイベント サブスクリプションを作成することです。
Blob コンテンツは、通常の Blob トリガー同様、content.bindings.myBlob で取得可能です。
{ "bindings": [ { "name": "myBlob", "type": "blobTrigger", "direction": "in", "path": "samples-workitems/{name}", // `<コンテナー名>/<Blob 名>` の書式が必要 "source": "EventGrid", "connection": "MyStorageAccountConnectionString" } ] }
Pros.
上に書いた通り、Blob トリガーのコンテンツ ハンドリングと Event Grid トリガーのリアルタイム性を、1 つのトリガー バインディング設定で実現できます。
Cons.
path プロパティについては、通常の Blob トリガーと同様なので、対象の Blob コンテナーを 1 つに決める必要があります。
また、この Event Grid Blob トリガーを使うには、Microsoft.Azure.WebJobs.Extensions.Storage の v5 以降が必要になります。
これはまだプレビューなので、サポートがベスト エフォートになります。
| コンテンツ取得 | リアルタイム性 | 信頼性 | |
|---|---|---|---|
| Event Grid Blobトリガー | 〇 | 〇 | △ ※プレビュー |
Event Grid トリガー + Blob バインディング
ここまでは単独のトリガー設定でしたが、他の機能 (入力バインディング) と組み合わせることで、さらにいいとこどりもできます。
仕組み
トリガー自体は Event Grid トリガーをそのまま使い、Blob 入力バインディングで Blob のコンテンツを取得します。
これは、Blob 入力バインディング設定の path に EventGrid トリガーで受信する JSON ペイロードに含まれる Blob の URL を設定することで実現できます。
{ "bindings": [ { "type": "eventGridTrigger", "name": "eventGridEvent", "direction": "in" }, { "type": "blob", "direction": "in", "name": "myBlob", "path": "{data.url}", // Event Grid トリガーからの JSON ペイロードから取得するバインディング式 "connection": "MyStorageAccountConnectionString" } ] }
Pros.
バインディングを組み合わせていますが、それぞれはサポートされているもので安心して使えますし、必要な設定/情報は Event Grid Blob トリガーと同じです。
Event Grid トリガーをそのまま使っているので、リアルタイム性も高くリトライもサポートしていますし、コンテンツのハンドリングについては、Blob 入力バインディングで context.bindings.myBlob から簡単にアクセスできます。
また Blob トリガーと違って、実は Blob 入力バインディングではコンテナーを 1 つに定める必要はないので、全てのコンテナーに対する処理ができます。
Cons.
弱点は、バインディング設定が 2 つ必要、ということくらいでしょうか。
| コンテンツ取得 | リアルタイム性 | 信頼性 | |
|---|---|---|---|
| Event Grid トリガー + Blob 入力バインディング |
◎ ※複数 Blob コンテナーに対応 |
〇 | 〇 |
まとめ
いくつかある Blob の保存をトリガーとした関数の実装方法について、機能面から比較をしてみました。
| コンテンツ取得 | リアルタイム性 | 信頼性 | |
|---|---|---|---|
| Blob トリガー | 〇 | △ ※ファイル数に依存 |
〇 |
| Event Grid トリガー | × | 〇 | 〇 |
| Event Grid Blobトリガー | 〇 | 〇 | △ ※プレビュー |
| Event Grid トリガー + Blob 入力バインディング |
◎ ※複数 Blob コンテナーに対応 |
〇 | 〇 |
ご参考になれば。