コンテンツに移動
アプリケーション開発

Workflows によるPic-a-Daily サーバーレス アプリのオーケストレーション

2021年2月25日
Google Cloud Japan Team

※この投稿は米国時間 2021 年 2 月 13 日に、Google Cloud blog に投稿されたものの抄訳です。

この 1 年で、私たち(AtamelLaforge)は Cloud Functions、App Engine、Cloud Run といった Google Cloud サーバーレス テクノロジーを利用した Pic-a-Daily という名前の写真共有アプリケーションを開発しました。これらのテクノロジーを組み合わせ、加えてサービス間通信のために Pub/Sub、写真メタデータの保存のために Firestore、さらには機械学習も利用しました。

https://storage.googleapis.com/gweb-cloudblog-publish/images/1_Shqfx7L.max-1400x1400.max-1200x1200.png

またこのアプリケーションを作るためのハンズオン ワークショップや、使用したテクノロジーについて説明するスライドも作成しました。ワークショップは一連の Codelab で構成されており、自分のペースで進められるようにしています。コードはすべてオープンソースで、GitHub リポジトリで公開しています。

第一段階: イベント ドリブン アーキテクチャ

Pic-a-Daily アプリケーションは徐々に進化しました。新しいサービスが追加されていくにつれて、下図に示す、疎結合したイベント ドリブンなアーキテクチャが生じました。

https://storage.googleapis.com/gweb-cloudblog-publish/images/2_XMbrwvr.max-1100x1100.max-1100x1100.png

このイベント ドリブン フローをまとめると次のようになります。

  1. ユーザーが App Engine のウェブ フロントエンドに写真をアップロードします。写真が Google Cloud Storage バケットに保存されると、ファイルの作成とイベントの削除がトリガーされ、Pub/Sub や Eventarc などのメカニズムを通じてプロパゲートされます。

  2. Cloud Functions の関数(画像分析)がファイル作成イベントに反応して Vision API を呼び出し、写真へのラベルの割り当て、主要な色の識別、一般公開して安全な写真かどうかのチェックを行います。これらの写真メタデータはすべて、Cloud Firestore に保存されます。

  3. Cloud Run サービス(サムネイル サービス)もファイル作成イベントに反応して高解像度イメージのサムネイルを生成し、別のバケットに保存します。

  4. Cloud Scheduler によってトリガーされる定期的なスケジュールに沿って、別の Cloud Run サービス(コラージュ サービス)が、最近の 4 つの写真のサムネイルからコラージュを作成します。

  5. 最後に、3 つ目の Cloud Run サービス(画像ガベージ コレクター)が、(最近一般提供になった)Eventarc を通じて受信したファイル削除イベントに応答します。高解像度イメージが写真バケットから削除されると、Cloud Run サービスによって画像のサムネイルと Firestore メタデータも削除されます。

これらのサービスは疎結合しており、それぞれ固有のロジックでイベントをスムーズに処理します。各サービスはそれぞれ個別にスケールできます。別のサービスが失敗しても動作を継続できるため、単一障害点は存在しません。イベントベースのシステムは、それに応答する他のイベントやサービスを組み込めば、現在のドメイン範囲を越えて拡張することができます。

しかし、そのような拡張したシステムは通常複雑になります。これは、すべてのサービスにまたがるビジネス プロセスにおいて、どの段階にいるかを簡単に確認できる場所が存在しなくなるためです。ビジネス プロセスに関していえば、イベントのフロー、およびサービス間の相互作用を捉えて把握することはさらに困難です。プロセス全体を把握できないため、特定のプロセスやトランザクションが成功したかどうかを知ることもできません。また、問題が発生したときに、エラー、リトライ、タイムアウトを適切かつ明確に処理することもできません。

私たちはサービスを追加し続けていくうちに、ベースとなる「ビジネスフロー」を見失いかけていました。システム内でなんらかのエラーが発生した際に、問題を切り分けてデバッグすることが困難になっていたのです。そこで、オーケストレーション アプローチについて調べることにしました。

Workflows によるオーケストレーション

Workflows は最近一般公開になったプロダクトであり、アプリケーションを再設計し、完全にイベント ドリブンなアプローチではなくオーケストレーション アプローチを使用するきっかけを提供します。オーケストレーション アプローチでは、イベントに応答するマイクロサービスの代わりに、事前定義された順序でマイクロサービスを呼び出す外部サービス(Workflows など)が使用されます。

Workflows を使用していくつかの再構築を行った後、以下のアーキテクチャが生まれました。

https://storage.googleapis.com/gweb-cloudblog-publish/images/3_temY387.max-1000x1000.max-1000x1000.png

オーケストレーション アプローチについてまとめます。

  • 他のアプローチと同様、App Engine はウェブ フロントエンドとしてユーザーから写真を受け取り、Cloud Storage バケットに保存します。

  • ファイル保存イベントによって 2 つの関数がトリガーされます。1 つは新しい写真の作成で、もう 1 つは既存の写真の削除です。どちらの関数でもワークフロー実行が作成されます。ファイル作成については、ワークフローが(Cloud Functions の関数コード経由ではなく宣言的に)Vision API への呼び出しを直接行い、REST API 経由で写真メタデータを Firestore に保存します。

  • その間に、Vision API の有用な情報を、Firestore に保存されるドキュメントに変換する関数があります。最初の画像分析関数が簡素化され、ワークフローによって、REST API が呼び出しを行ってデータ変換部分だけをそのまま残すようになりました。

  • 表示しても問題ない写真の場合、ワークフローが情報を Firestore に保存します。そうでない場合、ワークフローは終了します。

  • ワークフローのこのブランチは、Cloud Run のサムネイル サービスとコラージュ サービスを呼び出して終了します。従来のアプローチと似ていますが、Pub/Sub や Cloud Scheduler の設定は必要ありません。

  • ワークフローのもう一方のブランチは画像ガベージ コレクションに使われます。このサービスにはビジネス ロジックがなく、ほとんどが API 呼び出しであるため、完全に削除されました。代わりに、ワークフローがこれらの呼び出しを行います。

現在オーケストレーション アプローチでは、workflows.yaml ファイルによって、一元的にビジネスフローを表現することができます。ビジネスフローを表すチャートを Cloud Console で確認することもできます。

https://storage.googleapis.com/gweb-cloudblog-publish/images/4_zpsaVq7.max-1500x1500.max-1400x1400.png

Workflows UI にはどの実行がどのステップで失敗したかが表示されるため、膨大なログを調べて各サービス呼び出しを関連付けなくても、問題のある箇所を把握することができます。Workflows によって各サービスの呼び出しが適切に完了されます。また、Workflows にはグローバルなエラーおよびリトライのポリシーを適用することができます。

オーケストレーションを使用すると、ビジネスフローをより一元的かつ明確に捉えることができ、バージョン管理も可能になります。ワークフローの各ステップをモニタリングし、ワークフローにおけるエラー、リトライ、タイムアウトを明確に定義できます。特に Cloud Workflows を使用すると、Pub/Sub トピックのイベントに依存することなく、REST 経由でサービスを直接呼び出すことができます。さらに、プロセスに関連するすべてのサービスの独立性を保つことができるため、他のサービスが何をしているかを逐一把握する必要もありません。

もちろん短所もあります。アーキテクチャにオーケストレーターを追加すると、管理するコンポーネントが 1 つ増えることになり、それが単一障害点となってしまう可能性があります(幸いなことに、Google Cloud プロダクトには SLA が付帯しています)。最後になりますが、REST エンドポイントに依存すると、結合の度合いが増す可能性があるため、強力なペイロード スキーマと軽量なイベント フォーマットの間でバランスを取る必要があります。

学習した内容

Workflows の利用はさまざまな面で目新しく、共有に値する学びが得られました。

可視性の向上

ベースとなるビジネス ロジックの概要を YAML 宣言の形式で明確に表現できることは非常に便利です。各ワークフローの実行を可視化できたことが役に立ちました。その結果、ログを調べてさまざまなサービス実行を関連付けることなく、各実行で何が行われたかを明確に把握することができました。

よりシンプルなコード

元のイベント ドリブンなアーキテクチャでは、以下の 3 種類のイベントを処理する必要がありました。

  1. Cloud Functions と Cloud Storage の直接統合イベント

  2. Cloud Storage での、HTTP でラップされた Pub/Sub メッセージ イベント(Cloud Run 用)

  3. Eventarc の CloudEvents ベースの Cloud Storage イベント(Cloud Run 用)

そのため、各コードで各イベントの特性に対応する必要がありました。

読み込んでいます...

オーケストレーションを使用すると、シンプルな REST 呼び出しと HTTP POST の本文をパースするだけで済みます。

読み込んでいます...

より少ないコード

REST 呼び出しを(シンプルな認証付きの)宣言としてワークフロー定義に移したことで、サービスのコードを大幅に省くことができました。シンプルなデータ変換関数に軽量化されたサービスもあれば、完全になくなったサービスもあります。また、これまではワークフローで 2 つのパスをトリガーするには 2 つの関数が必要でしたが、今後 Eventarc と統合することで、それらの関数は必要なくなる可能性があります。

より少ないセットアップ

元のイベント ドリブンなアーキテクチャでは、サービスを関連付けるためには Pub/Sub トピックを作成して Cloud Scheduler と Eventarc をセットアップする必要がありました。Workflows では、これらがすべて不要になります。Workflows.yaml だけで、ビジネスフローに必要なセットアップをすべて行うことができます。

エラー対応

エラー対応も、いくつかの点でよりシンプルになりました。まず、エラーが発生するとフロー全体が停止するため、一連の呼び出しで成功したサービスと失敗したサービスを正確に把握できるようになりました。それから、エラーとリトライに関するグローバルなポリシーを適用できるようになりました。

学習曲線

しかし、必ずしもすべてが完璧というわけではありません。私たちは、Workflows の詳細なドキュメントがまだ揃っていない状態で新しいサービスを学習する必要がありました。もちろん、Workflows は一般公開されたばかりなので、今後はユーザーからのフィードバックによってドキュメントが徐々に改善されていくでしょう。

コードと YAML

アーキテクチャの再設計を進める中で、この疑問に何度も直面することになりました。「サービス内のコードでやるべきか、それとも Workflows を通じて YAML 定義から呼び出すべきか?」

Workflows では、ロジックの多くが、サービス内のコードではなく YAML のワークフロー定義ファイルに記述されます。通常は YAML よりコードの方が記述、テスト、デバッグを簡単に行うことができますが、Workflows のステップ定義よりも多くのセットアップおよびメンテナンスが必要になります。

API を呼び出すだけのボイラープレート コードであれば、YAML 宣言に変えるほうがよいでしょう。しかしコードがロジックも備えている場合は、そのままコード内に残した方がよいでしょう。YAML の方がテストしにくいためです。Workflows UI にはある程度のエラーレポート機能はありますが、サポート機能が豊富な本格的な IDE ではありません。開発マシン上の IDE で作業する場合でも、有効な YAML 構文しかチェックされないため、十分な機能が得られるとはいえません。

柔軟性の喪失

最後に触れておきたい特徴として挙げられるのが、柔軟性の喪失です。イベント経由でやり取りする、疎結合した一連のマイクロサービスの扱いは、ビジネス プロセスの厳密な定義を必要とする厳格なソリューションと比べて、極めて多岐にわたります。

コレオグラフィーかオーケストレーションか

どちらのアプローチも完全に有効ですが、それぞれに長所と短所があります。以前、Workflows を紹介したブログ投稿でこのトピックを取り上げました。どのような場合に一方が適しているといえるでしょうか?コレオグラフィーは、個々のサービスが密接に関連していない場合や、異なる制限付きコンテキストに存在し得る場合に適しています。一方オーケストレーションは、アプリケーションのビジネス ロジックを明確なフローチャートとして表現し、それをワークフロー定義で直接表現できる場合に適しています。

次のステップ

さらに理解を深めるには、Workflows の詳細とサポートされている機能についてのドキュメントをご参照ください。特に、リファレンス ドキュメントを確認されることをおすすめします。Workflows について取り上げたさまざまな短文記事もご参照いただけます。たとえば、さまざまなヒントとコツ、Workflows の紹介、Workflows の使用方法の概要コレオグラフィーとオーケストレーションについての分析などがあります。

Serverless Workshop では、イベントベースのアーキテクチャや同等のオーケストレーション アプローチを使用した具体的なユースケースについて学習できます。Cloud Functions、Cloud Run、App Engine、Eventarc、Workflows の Codelab が提供されています。特にラボ 6 は、私たちのように Workflows を使用してイベントベース モデルをオーケストレーションに変換する場合に参考になります。コードはすべて、GitHub でオープンソースとしてもご利用いただけます。

ワークフローのテストやニーズに関する皆様からのフィードバックをお待ちしております。Twitter(@glaforge@meteatamel)でお気軽にご連絡ください。

-デベロッパー アドボケイト Guillaume Laforge

-デベロッパー アドボケイト Mete Atamel

投稿先