[レポート]EventBridgeを使って疎結合なサーバーレスワークロードを作ろう #reinvent #SVS402

2020.12.29

re:Invent 2020のセッション「 Decoupling serverless workloads with Amazon EventBridge 」を聴講しましたのでレポートします。

EventBridgeの便利さをとてもわかり易く説明してくれます。後半のEventBridgeを使ったアーキテクチャーが興味深く、EventBridgeを多用したアプリケーションを作ってみたいなぁと思いました。

セッション概要

Event-driven architecture can help you decouple services and simplify dependencies as your applications grow. In this session, you learn how Amazon EventBridge provides new options for developers who are looking to gain the benefits of this approach.

イベント駆動アーキテクチャーは、アプリケーションの拡張時にサービス間を疎結合に保ち、依存関係をシンプルにしてくれるという点で有用です。このセッションでは、EventBridgeを使ってこのメリットを手に入れる方法を学ぶことができます。

  • Session ID: SVS402
  • Session Level: Expert - 400
  • Speaker: James Beswick, AWS Serverless Senior Developer Advocate

レポート

The challenges with microservices

※ challengesは「大変なこと」というような意味です。

最初はこんな感じのシンプルなアーキテクチャーでも… decoupled-v1

サービス拡張につれてだんだん複雑になっていきます。 decoupled-v2 decoupled-v3

  • ダウンストリームサービス(右側のサービスたち)はそれぞれリトライ方法を持つ必要があります。
  • オーダーサービス(左側のサービス)はダウンストリームサービスそれぞれのSDKを使う必要があるかもしれません。
  • ダウンストリームサービスが自身のAPIを持っている場合でも、オーダーサービスは各APIにアクセスする必要があります。
  • したがって、ダウンストリームサービス側で後方互換性の無いアップデートがある場合は、オーダーサービスチームも対応する必要があります。
  • こういった状況から、ダウンストリームサービスチームにとっては、オーダーサービスがサービスアップデートを妨げる「ブロック」となり得ます。

また、マイクロサービスは、正常稼働時はよいですが、 descoupled-happy エラーハンドリングは複雑になりがちです。以下の例はECサービスにおいて、注文を受けた後に在庫切れが発覚した場合です。各サービスにアクセスして、それぞれ取り消しや返金などの処理をトリガーする必要があります。 descoupled-messy

以上のように、マイクロサービスには色々と大変な部分がありますが、もちろん反対に利点もあります。

  • よく設計されたマイクロサービスアーキテクチャーは、サービス間を疎結合に保つことができます。
  • よりスケーラビリティを持つこともできます。
  • 拡張性を高くすることもできます。疎結合であるために既存サービスに影響を与えにくいからです。
  • 複雑性を抑えることもできます。
  • 可用性を高めることのできるパターンもたくさんあります。

Integration patterns with Amazon EventBridge

decoupled-eventbridge Amazon EventBridgeはサーバレスなイベントバスサービスです。イベントをワークロード全体の第一級オブジェクトにします。SaaSアプリケーション、AWSサービス、および独自のシステムからイベントを取り込んでルーティングするのに役立ちます。

key-features イベントバスの主要機能は以下2つです。

  • イベントプロデューサー(発行者)とコンシューマー(利用者)を(イベントバスを介したコミュニケーションにすることで)疎結合にする
  • イベントをフィルターしてルーティングする(ことにより適切なコンシューマーにのみイベントが届くようにする)

introduce-event-bus

先程のマイクロサービスの例にイベントバスを導入すると上記のようになります。オーダーサービスはイベントバスにイベントを送信するようにします。イベントバスにはルールが設定してあり、どのサービスがそのイベントを受け取るか決められています。いくつかのターゲットは全てのイベントではなく、特定のイベントのみ受け取るように設定されるかもしれません。

EventBridgeを使ったインテグレーションパターンをいくつかご紹介します。

1. Scalable webhook

scalable-webhook

Webhookはサービス関連携の手段として一般的ですが、弱点も抱えています。突然大量のトラフィックを受信し、バックエンドがそれに応えられるスケール性能を持っていない場合、機能停止が発生し得ます。Webhook呼び出し側がリトライもしくはエラーハンドリングロジックを持っていない場合はメッセージを失う可能性があります。

そこでこのScalable webhookパターンです。WebhookのHTTPエンドポイントはイベントバスに直接ルーティングされ、バスはSQSキューにイベントを渡します。Lambda関数を使ってSQSメッセージを処理していきます。もちろん他のサービスを使って処理をしても良いです。SQSを介することでリトライやエラー処理が容易になります。

他にも以下の利点があります。

  • イベントルールに他のターゲットを追加するだけでWebhookの宛先を簡単に変更追加できます。
  • Lambda関数の同時実行数をコントロールしてイベント処理スピードを調整できます。

このパターンのサンプルコードはこちらです。

2. Responding to workflows

respond StepFunctionsをEventBridgeと組み合わせて使うパターンです。StepFunctionsのWorkflowで管理する必要があるような複雑な処理が、他のサービス(他のチームが管理するサービス)と連携する拡張性をもたらします。

このパターンのサンプルコードはこちらです。

3. Integrating with AWS CloudTrail

with-cloudtrail 次はCloudTrailと連携するパターンです。イベントソースとして使います。多くのAWSサービスやアクションがEventBridgeにイベントを発行することができます。例えば、ユーザーがAWSコンソールにログインしたときや、リソースのタグを変更した際に発火するサーバレスなワークフローを作成することができます。

multiple-s3-buckets 上記の例は複数のS3バケットをLambdaのイベントソースとするパターンです。

(EventBridgeを使わず)S3のイベント通知機能でLambdaを呼び出す事もできますが、この場合、同一のイベントで発火するLambda関数を複数個設定することはできません。また、複数のバケットで同じルールで同じLambda関数を呼び出したくても、個々のバケットごとに設定する必要があります。

ですが、EventBridge経由でCloudTrailに記録されるS3イベントを拾うと、複数のバケットから、一つないしは複数のLambda関数をトリガーしたり、同じprefixやsuffixパターンで複数のLambda関数をトリガーしたりできます。例えばイベントソースとして「xxというprefix名を持つバケット(からのイベント)」というような設定にしておけば、動的にイベントソースとなるバケットを増減させることもできます。

このパターンのサンプルコードはこちらです。

Extending the AWS Cloud with (software as a service) SaaS partners

SaaSサービスとEventBridgeの連携もたくさん用意されています。現在約30のSaaSパートナーが存在しています。

  • パートナーリストは随時拡大中です。
  • ポーリングやWebhookを置き換えることができます。ポーリングはコンピュートインテンシブであり、データ更新結果を取得する際に難しいアプローチになりがちです。リアルタイムでないからです。また大きなペイロードの場合にうまく機能しないことがあります。Webhookもスケール性能に困難を抱えています。パブリックに呼び出せるエンドポイントを持つ必要があるので、それをセキュアに保つ必要もあります。
  • AWSイベントを扱う際と同様な方法でSaaSのイベントを処理できます。
  • よりセキュアになります。なぜならインターネット越しにAPIキーをやり取りするようなことをする必要が無いからです。
  • AWSマネージドなサービスであり、需要に応じて自動スケールします。

以下にSaaS連携の一例を紹介します。

Controlling access to resources

EventBridgeも他のAWSサービスと同様、IAMを介してきめ細やかなアクセスコントロールができます。

  • Lambda,SNS,SQS,CloudWatch Logsに関してはResource-based policyが必要です。
  • Tagに基づいたアクセス制限も便利です。

以下は細やかなアクセス制限をしたい場合の例です。

  • ユーザーが受け取れるイベントタイプを制限したい
    • events:sourceevents:detail type コンディションキーを使う
  • ルールに追加されるリソースを制限したい
    • events:TargetArnコンディションキーを使う
  • AWS CloudTrailからのイベントを制限したい
    • events:detail.userIdentity.principalIdコンディションキーを使う

Decoupling architecture with events and AWS Serverless Application Model (SAM)

Example: Document indexer application

document-indexer-application S3バケットにアップロードされた文書ファイルを分析してメタデータをElasticsearch Serviceに格納するアプリケーションです。

このアプリケーションは拡張性に欠けます。各処理が密結合しています。

そこでEventBridgeを使って疎結合にします。ロジックをシンプルに、理解しやすくできました。

  • CloudTrailイベントをリッスンすることで、動的にS3バケット群をイベントソースとしてリッスンできます。
  • 各ファイルタイプ毎の変換処理は、EventBridgeをイベントソースとするLambda関数として実装しました。これにより新しいファイルタイプの変換処理を実装するのがやりやすくなりました。
  • Elasticsearch Serviceにデータを登録している部分も、イベントターゲットを変えるだけで他のリソースに簡単に変更することができるようになりました。

Using the Amazon EventBridge schema registry

イベントドリブンな疎結合なアプリケーションを作る際に一つ困難なことは、イベントフォーマット、もしくはスキーマの変更に追従することです。新バージョンのサービスがリリースされる際に、スキーマが変更されたり新しい要素が追加されたりします。

そういうときはEventBridgeのSchema Registryという機能が便利です。EventBridgeイベントバス上のイベントの発見、作成、管理を担います。VSCodeとJetBrains向けのToolkitも用意されています。Schema Registry上のイベントスキーマはCodeBinding機能によって、そのイベントを扱うJava、TypeScript、Pythonのコードをダウンロードすることも可能です。

まとめ

  • EventBridgeはイベントバスを介してマイクロサービスを疎結合にすることができます。
  • スケーラビリティがあります。自動でスケールします。
  • 各イベントコンシューマーを疎結合に実装できるので、拡張性があります。SaaSパートナーも増え続けています。
  • IAMを用いてきめ細やかなアクセスコントロールが可能です。
  • SAMを使って実装すればすばやく開発することが可能です。

視聴URL