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)」が基本だ。ネットワーク障害やリトライにより、同じメッセージが複数回配信される可能性がある。購読者側でべき等性を確保する設計が必須だ。
体系的に学ぶなら関連書籍を参照してほしい。