Gridwich パイプラインは、2 つの新しい方法である Azure Event Grid サンドイッチ および Terraform サンドイッチを使用して、メディア資産を取り込み、処理、保存、配信します。
アーキテクチャ
Gridwich アーキテクチャは、非同期イベント処理とコードとしてのインフラストラクチャという要件に対応する 2 つの "サンドイッチ" を特徴としています。
Event Grid サンドイッチでは、外部の saga ワークフロー システムからのメディア エンコードなどのリモートで実行時間の長いプロセスを、2 つの Event Grid ハンドラーで挟み、抽象化します。 挟むことにより、外部システムが要求イベントを送信し、スケジュールされたイベントを監視して、数分から数時間後に得られる最終的に成功または失敗の応答を待つことができます。
このアーキテクチャの Visio ファイルをダウンロードします。
Terraform サンドイッチは、コードとしてのインフラストラクチャをサポートするように更新された、複数ステージの Terraform パターンです。 インフラストラクチャとソフトウェアのリリースを分離することは、Terraform が Event Grid サブスクリプションをデプロイする前に、Azure Functions アプリをリリースして実行する必要があることを意味します。 この要件に対処するために、CI/CD パイプラインには次の 2 つの Terraform ジョブがあります。
- Terraform 1 では、Azure Event Grid サブスクリプションを除くすべてのリソースが作成されます。
- Terraform 2 では、ソフトウェアが起動して実行された後、Event Grid サブスクリプションが作成されます。
このようにして、Terraform はソフトウェアの成果物をデプロイする前に、すべての Azure リソースを作成できるわけではない場合でも、ソリューション インフラストラクチャを完全に管理およびデプロイできます。
ワークフロー
Gridwich の要求と応答プロセスは、次の要求を対象とします。
- 作成
- トランスポート
- Reception
- Gridwich コンポーネントへのディスパッチ
- 確認とアクション
- 応答
次の手順では、外部システムと Gridwich の間の要求と応答のプロセスについて説明します。 Gridwich では、外部システムは MAM および saga ワークフロー オーケストレーション システムです。 Gridwich 操作メッセージ イベントの正確な形式については、Gridwich メッセージ形式に関するページを参照してください。
外部システムは要求を作成し、要求ブローカーに送信します。
要求ブローカーは、従来のパブリケーション サブスクリプション モデルの Gridwich 要求リスナーに要求をディスパッチします。 このソリューションでは、要求ブローカーは Azure Event Grid です。 すべての要求は、Event Grid のイベント スキーマを使用してカプセル化されます。
Gridwich Azure Functions アプリは、Event Grid からイベントを使用します。 スループットを向上させるために、Gridwich では、Azure Functions により提供される Event Grid バンディング ポーリング モデルではなく、HTTP エンドポイントが Event Grid モデルが開始するプッシュ モデルとして定義されます。
Azure Functions アプリは、イベントのプロパティを読み取り、Gridwich コードのうち、そのイベントの種類とバージョンを処理する部分にイベントをディスパッチします。
現在の要求で動作するすべてのハンドラーでは、共通の EventGridHandlerBase クラスを使用して、要求を受信したときにすぐに受信確認メッセージが送信されます。 次に、ハンドラーが派生クラスに作業をディスパッチします。
Gridwich 要求ワークフローは、実質的に同期または非同期になることができます。 実行が簡単で、完了までの時間が短い要求の場合、同期ハンドラーによって処理され、受信確認が送信されたほぼ直後に成功または失敗のイベントが返されます。
長時間実行される要求の場合は、非同期ハンドラーにより要求が評価され、引数が検証され、実行時間の長い操作が開始されます。 次に、ハンドラーにより、作業アクティビティが要求されたことを確認するスケジュール済みの応答が返されます。 作業アクティビティの完了時に、要求ハンドラーは、作業に成功または失敗の完了イベントを提供する役割を担います。
イベント パブリケーション サービスから、受信確認、失敗、スケジュール済み、または成功のメッセージが Event Grid 要求ブローカーに通信されます。
Azure Function のイベント パブリッシャーは、応答イベントを Event Grid トピックに送信します。このトピックは、リライアブル メッセージ ブローカーとして機能します。 外部システムはトピックをサブスクライブし、メッセージを使用します。 Event Grid プラットフォームでは、外部システムへのパブリケーションのための通常の再試行ロジックが提供されます。
メッセージの順序
受信確認は成功とスケジュール済みの応答の両方に先行しますが、Gridwich は、スケジュールされた応答が常に対応する成功応答の前になることを保証しません。 有効な応答シーケンスは、受信確認 > スケジュール済み > 成功か、受信確認 > 成功 > スケジュール済みのどちらかです。
要求の失敗
要求の失敗は、無効な要求、事前条件の不備、処理エラー、セキュリティ例外、またはハンドルされない例外によって発生することがあります。 ほとんどのエラーには同じメッセージ形式があり、元の操作コンテキスト値が含まれています。 共通の EventGridHandlerBase クラスは、通常、Azure Function イベント パブリッシャー インターフェイスを介して Event Grid に失敗応答を送信します。 また、Application Insights でも構造化されたログを使用してエラーがログに記録されます。
操作コンテキスト
外部システムによって、1 日、1 時間、または 1 秒あたり数千の要求が生成される場合があります。 Gridwich に対する各要求イベントには、operationContext
という名前の JSON オブジェクト プロパティを含める必要があります。
要求に {"id"="Op1001"}
のような操作コンテキストが含まれている場合、各 Gridwich {"id"="Op1001"}
には、要求が短時間で実行されているか長時間実行されているかにかかわらず、対応する不透明な操作コンテキストを含める必要があります。 この操作コンテキストは、非常に長時間実行される要求の場合でも有効期間を通じて保持されます。
応答要件は、"同じ" ではなく "対応する" JSON オブジェクトです。 コンテキストのミュートなどの Gridwich 機能により、返された JSON オブジェクトが外部システムによってトップダウン方式で処理されるという事実を利用 ます。
具体的には、外部システムには次のような特徴があります。
プロパティの順序に依存しないため、Gridwich は同じプロパティを持つオブジェクトを場合によっては異なる順序で返すことができます。 たとえば、
{"a":1,"b":2}
と{"b":2,"a":1}
です。追加のプロパティが存在していても問題ありません。そのため、
{"b":2,"a":1}
を受け取った Gridwich は、{"a":1,"b":2,"~somethingExtra":"yes"}
を有効に返すことがあります。 競合の可能性を最小限に抑えるために、Gridwich では、追加されたプロパティの名前の前にチルダ (~) を付けます。たとえば、~muted
のようになります。JSON 形式の依存関係はありません。 たとえば、JSON の文字列表現内で空白文字の埋め込みが行われる場所については、想定されていません。 Gridwich では、JSON オブジェクトの文字列表現で不要な空白を圧縮することによって、書式設定の依存関係がないことを活用します。 See JSONHelpers.SerializeOperationContext を参照してください。
Saga 参加要素と操作コンテキスト
Gridwich saga オーケストレーション システムでは、各 saga 参加要素は、1 つまたは複数の作業をシステムに提供します。 各 saga 参加要素は、他の参加者とは関係なく動作し、複数の saga 参加要素が 1 つの要求に対して動作する可能性があります。
各 saga 参加要素は操作コンテキストを保持する必要がありますが、異なる方法で実装できます。 次に例を示します。
- 実行時間の短い同期操作では、操作コンテキストが保持されます。
- Azure Storage には、ほとんどの操作で
ClientRequestId
と呼ばれる不透明な文字列プロパティが用意されています。 - 一部のサービスには
Job.CorrelationData
プロパティがあります。 - 他のクラウド API では、進行状況、完了、または失敗を通知するときに返すことができる不透明な操作コンテキストと同様の概念を提供されます。
saga と saga の参加要素の詳細については、Saga のオーケストレーションに関するページを参照してください。
同期と非同期ハンドラー
システム内のすべてのイベント ハンドラーでは、共通の EventGridHandlerBase クラスを使用して、応答イベントの受信確認要求、エラー処理、パブリケーションなどの汎用サービスが提供されます。 イベント パブリケーション サービスから、受信確認、失敗、スケジュール済み、または成功のメッセージが Event Grid 要求ブローカーに通信されます。
現在の要求との連携を計画しているすべてのハンドラーは、要求を受信したときに受信確認を提供する必要があります。 基底クラスからすぐに受信確認メッセージが送信され、その後、その作業は派生クラスにディスパッチされます。
同期イベント処理
実行が簡単で、完了までの時間が短い要求の場合、ハンドラーによって同時に処理が行われ、受信確認が送信されたほぼ直後に成功イベントと操作コンテキストが返されます。
.
たとえば、ChangeBlobTierHandler は単純な同期フローです。 ハンドラーにより、要求データ転送オブジェクト (DTO) が取得され、1 つのサービスの呼び出しと作業の実施までの待機が行われ、成功または失敗の応答が返されます。
非同期イベント処理
一部の要求は長時間実行されます。 たとえば、メディア ファイルのエンコードには数時間かかることがあります。 その場合は、非同期要求ハンドラーにより要求が評価され、引数が検証され、実行時間の長い操作が開始されます。 次に、ハンドラーにより、作業アクティビティが要求されたことを確認するスケジュール済みの応答が返されます。
作業アクティビティの完了時に、要求ハンドラーは、作業に成功または失敗の完了イベントを提供する役割を担います。 ステートレスのまま、ハンドラーにより元の操作コンテキストが取得され、完了したイベント メッセージ ペイロードに配置される必要があります。
たとえば、BlobCopyHandler は、単純な非同期フローを示しています。 ハンドラーにより、要求 DTO が取得され、1 つのサービスの呼び出しと作業の開始までの待機が行われ、成功または失敗の応答が発行されます。
実行時間の長い要求フローを完了するために、BlobCreatedHandler ではプラットフォーム イベント Microsoft.Storage.BlobCreated
が使用され、元の操作コンテキストが抽出され、成功または失敗の完了応答を発行します。
実行時間の長い Functions
Gridwich によって新しい Functions アプリがデプロイされると、実行時間の長いプロセスがドロップされる可能性があります。 これらのプロセスが突然終了した場合、ステータスはなく、呼び出し元にレポートは返されません。 Gridwich では、長時間実行されている関数の移行を適切に処理しながら、新しい Functions アプリをデプロイし、またメッセージを漏らさないようにする必要があります。
ソリューションには次のものが必要です。
- Gridwich アプリの実行中のインスタンスの状態を保持しない。
- 新しいものがデプロイされているか、新しいメッセージが同じアクティビティを要求しているからといって、プロセスを強制終了しない。
- Durable Functions、Functions アプリ、Logic Apps、Azure Container Instances などの追加の Azure ワークロードは呼び出されない。
Gridwich では Azure Functions スロット デプロイおよびキャンセル トークンが使用され、これらの要件を満たした信頼性の高い、長時間実行される関数を実現します。
次の図は、ほとんどの Gridwich ジョブがどのように機能するかを示しています。 緑色のボックスは、Gridwich から外部サービスに渡されるジョブを表します。 Gridwich は、イベントドリブン方式でステータスに反応します。 赤色のボックスは、Gridwich 自体で長時間実行されている関数を示しています。
Functions ランタイムにより、アプリケーションのシャットダウン時にキャンセル トークンが追加されます。 Gridwich によりトークンが検出され、すべての要求と現在実行中のプロセスのエラー コードが返されます。
スロットの展開では、新しいソフトウェアのバージョンが展開されます。 運用スロットには実行中のアプリケーションがあり、ステージング スロットには新しいバージョンがあります。 Azure では一連のデプロイ手順が実行され、次にスロット インスタンスがスワップされます。 古いインスタンスは、プロセスの最後の手順として再起動されます。
Gridwich では、ホスト名を再マップした後 30 秒間の待機があります。したがって、HTTP によってトリガーされる関数の場合、古い運用スロットに対して再起動する前に少なくとも 30 秒が Gridwich により保証されます。 他のトリガーは、アプリ設定の更新を待機するメカニズムを持たないアプリ設定によって制御される場合があります。 これらの関数は、前の運用スロットが再起動する直前に実行が開始された場合に、中断されるリスクがあります。
詳細については、Azure Functions のスロット スワップ中に起こることに関するページと「Azure Functions デプロイ スロット」を参照してください。
コンポーネント
Gridwich メディア処理ソリューションでは、Azure Event Grid、Azure Functions、Azure Blob Storage、Azure Logic Apps、および Azure Key Vault を使用します。 CI/CD および saga オーケストレーション プロセスでは、Azure Repos、Azure Pipelines、および Terraform を使用します。
Azure Event Grid では、非同期メディア イベント処理を可能にする 2 つの sandwiched Event Grid ジョブを使用して、Gridwich イベントのルーティングが管理されます。 Event Grid は、信頼性の高い要求配信エンドポイントです。 Azure プラットフォームでは、必要な要求配信エンドポイントのアップタイムと安定性が提供されます。
Gridwich は、 Event Grid スキーマ
Event.Data
プロパティ オブジェクト内のイベントをカプセル化します。このオブジェクトは、Event Grid ブローカーとトランスポート層に対して非透過的です。 Gridwich では、eventType
およびdataVersion
オブジェクト フィールドも使用され、イベントがルーティングされます。 Event Grid 要求ブローカーを他のパブリケーション サブスクリプションのイベントブローカーに置き換えることができるように、Gridwich の依存関係は可能な限り少ないイベント フィールドになっており、topic
またはsubject
のフィールドは使用しません。Azure Functions では、インフラストラクチャを明示的にプロビジョニングしたり管理したりする必要なく、イベントトリガー型のコードを実行できます。 Gridwich は、さまざまな関数の実行をホストする Azure Functions アプリです。
Azure Blob Storage では、スケーラブルでコスト効率に優れたクラウド ストレージと、メディア資産などの非構造化データへのアクセスが提供されます。 Gridwich では、Azure Storage ブロック BLOB とコンテナーの両方が使用されます。
Azure Key Vault により、Azure とサードパーティのアプリやサービスが使用する暗号化キー、パスワード、その他のシークレットが保護されます。
Azure DevOps は、Azure と統合される、Git ベースのコード リポジトリや自動ビルドおよびリリース パイプラインを含む、開発者および運用サービスのセットです。 Gridwich では、Azure Repos を使用してコード プロジェクトと、CI/CD およびその他のワークフローの Azure Pipelines が格納および更新されます。
Terraform は、インフラストラクチャとサービスをプロビジョニングおよび管理するためにコードとしてインフラストラクチャを使用するオープンソース ツールです。
代替
Durable Functions には、長時間実行される操作のための組み込みの状態ストアがあるため、非透過的な操作コンテキストを提供することもできます。 Durable Functions により、操作内に一連のタスクを作成し、操作の入力または出力として操作コンテキストを保存することができます。 実際、Gridwich ではすべての作業アクティビティに Durable Functions を使用できますが、この方法ではコードの複雑さが増加します。
EventGridHandlerBase を
RequestHandlerBase
にリファクタリングし、Event Grid オブジェクトまたは型へのリンケージを削除することによって、Event Grid インフラストラクチャとの分離を向上させることができます。 このリファクタリングされたクラスは、トランスポート固有のオブジェクトの種類ではなく、基本 DTO でのみ処理します。 同様に、IEventGridDispatcher は、特定のEventGridDispatcher
実装を持つIResponseDispatcher
になる可能性があります。また、Gridwich.SagaParticipants.Storage.AzureStorage ライブラリには、他の saga 参加要素が使用するストレージ サービスも含まれています。 コア プロジェクトにインターフェイスを配置すると、制御の反転 (IoC) の問題が回避されますが、インターフェイスを別のコア ストレージ インフラストラクチャ ゲートウェイ ライブラリに抽出することができます。
Gridwich Functions アプリでは、依存関係挿入を使用して、特定のイベントの種類とデータ バージョンに対して 1 つ以上の要求ハンドラーが登録されます。 アプリでは Event Grid イベント ハンドラーのコレクションと共に EventGridDispatcher が挿入され、ディスパッチャーはハンドラーに対してクエリを実行して、イベントを処理するものを決定します。
または、Event Grid プラットフォームで提供されるイベント サブスクリプションとフィルター処理メカニズムを使用することもできます。 このメカニズムは、1 つの Azure 関数が 1 つのイベントハンドラーだけをホストする、1 対 1 デプロイ モデルを適用します。 Gridwich では 1 対多 モデルが使用されていますが、クリーン アーキテクチャであるため、1 対 1 のソリューションをリファクタリングすることは困難ではありません。
モノリシック Gridwich アーキテクチャではない、別のマイクロサービスについては、マイクロサービスの代替に関するページを参照してください。
シナリオの詳細
有名なマス メディアとエンターテインメント複合企業は、オンプレミスのビデオ ストリーミング サービスを、ビデオ資産を取り込み、処理、および公開するためのクラウドベースのソリューションに置き換えました。 主要な目的は、Azure クラウドの容量、コスト、柔軟性を活用して、以下を行うことでした。
- 生のビデオ ファイルを取り込み、処理して公開し、メディア要求を処理する。
- エンコードと新規の取り込みの両方と配信の機能を大規模に、かつクリーンに設計されたアプローチで向上させる。
- メディア資産管理 (MAM) パイプラインの継続的インテグレーションと配信 (CI/CD) を実行する。
これらの目標を達成するために、Microsoft のエンジニアリング チームは、外部の saga ワークフロー オーケストレーション システムによって駆動されるステートレスなイベント処理フレームワークである Gridwich を開発しました。
考えられるユース ケース
エンジニアリング チームは、以下の原則と業界標準に合わせて Gridwich を開発しました。
Gridwich システムには、Azure でメディア資産を処理および配信するためのベスト プラクティスが実装されています。 Gridwich システムはメディア専用ですが、メッセージ処理およびイベント フレームワークは、任意のステートレス イベント処理ワークフローに適用できます。
このシナリオのデプロイ
- GitHub の Gridwich リポジトリに移動します。
- Azure DevOps の設定から始めて、すべての手順に従います。
関連リソース
- Azure Pipelines 用の Terraform スターター プロジェクト
- Azure Function と Event Grid および Terraform サンドイッチのサンプル。 Terraform サンドイッチを使用して、Terraform を介して Azure Function を Event Grid にサブスクライブします。
- Azure Storage を使用した MediaInfoLib。 クロスプラットフォームの .NET Core を使用して Azure Storage に格納されているメディア ファイルのレポートを取得する Azure Functions とコンソールのサンプル。
- Event Grid Viewer Blazor。 Blazor と SignalR を使用した Event Grid Viewer アプリケーションで、Microsoft Entra 認可がサポートされています。
- Azure Storage 用の管理サービス ID を使用する Azure Function。 Azure Functions と Azure Storage 間で管理サービス ID を使用します。