Pub/Sub

発行者と購読者が直接通信せず、メッセージブローカーを介して非同期にメッセージを交換するパターン

メッセージング分散システム

Pub/Sub とは

Pub/Sub (Publish/Subscribe) は、メッセージの発行者 (Publisher) と購読者 (Subscriber) が直接通信せず、トピックやチャネルを介して非同期にメッセージを交換するパターンである。発行者は「誰が購読しているか」を知らず、購読者は「誰が発行したか」を知らない。この疎結合性がマイクロサービス間の連携に適している。

Observer パターンと似ているが、Pub/Sub はメッセージブローカーが仲介する点が異なる。Observer はオブジェクト間の直接的な通知であり、プロセス内で完結する。Pub/Sub はプロセスやサービスの境界を越えて機能する。

ポイントツーポイントとの違い

観点 Pub/Sub ポイントツーポイント (キュー)
配信先 全購読者に配信 (ファンアウト) 1 つのコンシューマーだけが処理
用途 イベント通知、データ同期 タスクの分散処理、ワークキュー
メッセージの消費 各購読者が独立して消費 1 つ消費されたら消える
AWS サービス SNS, EventBridge SQS
「注文が作成された」を通知 → 在庫、決済、通知が各自処理 「画像をリサイズせよ」→ 1 つのワーカーが処理

実務では両方を組み合わせる。SNS (Pub/Sub) で複数の SQS キュー (ポイントツーポイント) にファンアウトし、各キューのコンシューマーが独立して処理する「SNS + SQS ファンアウト」パターンが定番だ。

AWS での実装パターン

SNS + SQS ファンアウト

最も一般的な Pub/Sub パターン。SNS トピックに発行し、複数の SQS キューが購読する。

注文サービス → SNS (OrderCreated)
                ├→ SQS (在庫キュー) → Lambda (在庫引当)
                ├→ SQS (決済キュー) → Lambda (決済処理)
                └→ SQS (通知キュー) → Lambda (メール送信)

SQS を挟むことで、各購読者が独立してリトライ・スケーリングできる。SNS から Lambda を直接呼び出すこともできるが、SQS を挟む方がエラーハンドリングが柔軟だ (DLQ、可視性タイムアウト、バッチ処理)。

EventBridge

EventBridge はルールベースのフィルタリングで、条件に合致する購読者にのみイベントを配信する。SNS が「全購読者に配信」なのに対し、EventBridge は「条件に合う購読者だけに配信」する高度な Pub/Sub だ。

{
  "source": ["order-service"],
  "detail-type": ["OrderCreated"],
  "detail": {
    "total": [{ "numeric": [">=", 10000] }]
  }
}

この例では、1 万円以上の注文だけを特定の Lambda に配信する。

メッセージの順序保証

標準の SNS/SQS は順序を保証しない。順序が重要な場合の選択肢は以下のとおり。

サービス 順序保証 スループット 用途
SNS + SQS (Standard) なし 無制限 順序不問のイベント通知
SNS FIFO + SQS FIFO あり (メッセージグループ単位) 300 msg/s 順序が重要な処理
Kinesis Data Streams あり (シャード単位) シャード数 × 1,000 msg/s 高スループットのストリーム処理

よくある失敗パターン

購読者の障害が発行者に波及

SNS から Lambda を直接呼び出す構成で、Lambda がエラーを返すと SNS がリトライする。リトライが繰り返されると、SNS のスロットリングが発生し、他の購読者への配信にも影響する。SQS を挟めば、障害は該当キューに閉じ込められる。

メッセージの重複処理

Pub/Sub は「少なくとも 1 回配信 (at-least-once)」が基本だ。ネットワーク障害やリトライにより、同じメッセージが複数回配信される可能性がある。購読者側でべき等性を確保する設計が必須だ。

体系的に学ぶなら関連書籍を参照してほしい。

関連用語