AWSは多彩なサービスを提供しており、同じ機能を複数の方法で実装できることが少なくありません。メッセージングの分野でも、AWSはSimple Notification Service(SNS)、Simple Queue Service(SQS)、EventBridge、Kinesis、Managed Streaming for Apache Kafka(MSK)など、さまざまなサービスを揃えています。一見すると、これらのサービスの一部は機能が重複しているようにも見えるでしょう。本記事では、私が定番としているアーキテクチャを紹介し、それが大半のケースにおいて最もシンプルで、コスト効率が高く、堅牢な選択肢だと考える理由を解説します。
イベント駆動アーキテクチャ
イベント駆動システムを構成するコンポーネントは、イベントの発行(publish)と購読(subscribe)を通じて互いにやり取りします。この非同期連携には、非機能面で大きな利点があります。たとえば、連携するコンポーネント同士のライフサイクルを切り離せます。一部のサービスが利用できなくなってもシステムは一定程度動作を続けられるため、コンポーネントの更新デプロイやシステムの進化に伴う調整コストも抑えられます。
基本的なイベント駆動連携は、2つの要素で成り立ちます。コンポーネントが自身のライフサイクル上の重要な出来事を表すイベントを発行できること、そしてシステム内の他のコンポーネントが発行したイベントに反応(購読)できることです。これを実装するために活用できるマネージドサービスを見ていきましょう。
イベントの発行:SNS
AWS Simple Notification Service(SNS)はフルマネージドのサービスで、システム内の他のコンポーネントが受け取る通知を送信できます。サーバーレスであることと低価格であることから、SNSはイベント発行に最適な候補です。図1は、「Producer」というサービスがSNSトピックを介してイベントを発行する様子を示しています。

図1:「Producer」サービスがSNSトピックにイベントを発行する。
では、図の右側にある「Consumer」サービスはどうすればよいでしょうか。Producerが発行したメッセージを、どうやって購読すればよいのでしょうか。
SNSは、HTTP、AWS Lambda関数のトリガー、SMSなど、複数のプロトコルでのメッセージ配信に対応しています。理屈の上では、ConsumerがHTTPエンドポイントを公開し、それをSNSトピックの宛先に指定することも可能です(図2)。

図2:SNSトピックはHTTPエンドポイントへメッセージを転送できる。だが、これは最適な解だろうか?
しかし、本当にこれが最適でしょうか。ProducerとConsumerの2つのサービスが別々のチームに属しているとすると、SNSトピックの所有者は誰になるのでしょうか。Producer側のチームはトピックが自チームのメッセージを正しく受信できるよう設定を保たなければならず、Consumer側のチームは宛先が常に正しいことを確認しなければなりません。このような共有所有はトラブルの種になりがちです。別の選択肢を検討してみましょう。
イベントの購読:SQS
AWS SQSはフルマネージドのイベントキューで、プロデューサーが生成したメッセージ(イベント)を、コンシューマーが処理するまで一時的に保持します。複数のコンシューマー間で負荷分散しながら分散イベント処理を実現でき、イベント駆動ワークフローにおける耐障害性の確保に欠かせません。私見ですが、SNSトピックよりもキューの可視性が格段に高く、メッセージをコンシューマーへ届ける方法を柔軟に制御できる点も大きな魅力です。
SQSはSNSトピックがサポートする宛先の1つですので、図3のように「Consumer」サービスが処理するメッセージ用のキューをセットアップしましょう。

図3:イベント消費の仕組みとしてSQSを利用する。
この構成にすれば、所有権の境界が明確になります。
- メッセージ発行に使うSNSトピックは、発信側サービス(Producer)を担当するチームのもの。
- メッセージ消費に使うSQSキューは、購読側サービス(Consumer)を担当するチームのもの。
2つのサービス間の関心事の分離は、システムのアーキテクチャにも反映させる必要があります。
SNS + SQS:シンプルなEDA
マイクロサービスは明確に定義された公開インターフェースを通じてデータへのアクセスを提供すべきであり、データベースは実装の詳細としてコンシューマーから隠蔽すべきだ——これは広く受け入れられている考え方です。永続化の仕組みをこのように厳格にカプセル化することで、所有権の境界がはっきりし、マイクロサービスを進化させる柔軟性が高まり、公開インターフェースを細かく制御できるようになります。
システムが利用するメッセージバスもまた、もう1つの永続化メカニズム——機能はかなり限定的ですが——にすぎず、同様に扱うべきです。そのため、図4のように、各(マイクロ)サービスにはデータベースに加えて、イベントを発行するためのSNSトピックと、イベントを受け取るためのSQSキューが必要になります。

図4:EDAでは、データベースだけでなくメッセージング機構(SNSとSQS)についても明確な所有権の境界を定める必要がある。
サービス間を結ぶ矢印——トピックからキューへの購読関係——は、サービスそのものよりも一段上のアーキテクチャ抽象レイヤーに属します。たとえば、サービスごとにCloudFormationテンプレートを用意し、それらを組み合わせたシステム全体については、より上位のCloudFormationテンプレートを用意するイメージです。後者が購読関係の定義を担当します。
付け加えておくと、購読しているからといって発行されたすべてのイベントが無条件にコンシューマーへ送りつけられるわけではありません。購読(subscription)にはフィルターを指定でき、各コンシューマーに関連するイベントだけを転送できます。
このアプローチは、分散システムのシンプルさと柔軟性に欠かせないスマートエンドポイント、ダムパイプ(smart endpoints, dumb pipes)の原則に沿ったものです。この原則では、知性——つまりロジック——はサービス自身(エンドポイント)に持たせるべきであり、連携に用いるインフラ要素(パイプ)に持たせるべきではないとされています。パイプ、すなわちメッセージング基盤と通信チャネルは、サービス間でデータを確実に運ぶことだけに専念すべきです。狙いは、サービス間の依存を減らし、スケーリングやデバッグ、開発の高速化を可能にしつつ、高度なミドルウェアにつきもののボトルネックや複雑さを避けることにあります。
では、AWSで利用できる他のメッセージングサービスについても見ていきましょう。
その他のメッセージ配信サービス
冒頭で述べたとおり、AWSにはメッセージング関連のマネージドサービスが他にも数多く存在します。ここではそれらを簡単に取り上げ、なぜ80%のケースで前述のソリューションのほうが適していると考えるのかを説明します。
EventBridge
SNSとSQSの先頭の「S」は「Simple(シンプル)」を表し、これは伊達ではありません。SNSとSQSはあくまでシンプルなサービスです。一方、EventBridgeはメッセージのフィルタリングやルーティングのルールにおいて、はるかに柔軟性があります。私の見立てでは、EventBridgeはSOA時代のエンタープライズメッセージバスの概念に近い存在です。ダムパイプではなく、システム内のすべてのコンポーネント間、さらには複数システム間でイベントを受信・ルーティングする中心拠点が手に入ります。もちろんEventBridgeにも適したユースケースがあり、たとえばサードパーティ製システムとの統合が必要な場合などに有効です。
KinesisとMSK(マネージドKafka)
KinesisとMSKは、いずれもストリーミングデータを扱うためのサービスです。ストリーミングデータはイベント駆動アーキテクチャの一形態とも言え、どちらも非同期に発行・消費されるメッセージを扱う点は共通しています。ただし利用パターンは異なります。従来のEDAが個々のイベントやメッセージに焦点を当てるのに対し、ストリーミングデータでは関連するイベントの連続的な流れを処理する必要があり、従来のメッセージバス系ソリューションでは効率的に扱えない場合があるのです。だからこそKinesisやMSKといったツールが存在するわけです。連続したメッセージの流れを処理する必要がないのであれば、SNSやSQSのようなシンプルなツールを使ったほうが、システムの構成もすっきりします。
Amazon MQ
Amazon MQは、ActiveMQやRabbitMQといったプロトコルに対応したマネージドのメッセージブローカーサービスです。レガシーシステムをクラウドへ移行する場合や、複数のクラウド環境にまたがって変更を加えずに動作させる必要があるシステムで特に有用です。Amazon MQは高度なパターンに対応したフル機能のメッセージブローカーですが、SNSとSQSのシンプルさと比べると、運用負荷や複雑さが増す点には注意が必要です。
シリーズ記事一覧
- AWSで実現するイベント駆動アーキテクチャ 第1回:基礎編(本記事)
- AWSで実現するイベント駆動アーキテクチャ 第2回:応用基礎編
- AWSで実現するイベント駆動アーキテクチャ 第3回:発展基礎編
初出: https://vladikk.com 。
本記事では、SNSとSQSを使ってイベントを発行・消費するAWS上のイベント駆動アーキテクチャ(EDA)の実装方法を解説しました。SNSとSQSを組み合わせることで、所有権の境界が明確で、シンプルかつコスト効率に優れ、柔軟性と耐障害性を兼ね備えたソリューションを構築できることをご理解いただけたはずです。