Pub/Sub

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

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

Pub/Sub とは

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

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

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

両者の分かれ目は「1 つのメッセージを何人が受け取るか」にある。Pub/Sub では購読者全員が同じメッセージのコピーを受け取り、ポイントツーポイントでは 1 つのコンシューマーが取り出した時点で他からは見えなくなる。

観点Pub/Subポイントツーポイント (キュー)
配信先全購読者に配信 (ファンアウト)1 つのコンシューマーだけが処理
用途イベント通知、データ同期タスクの分散処理、ワークキュー
メッセージの消費各購読者が独立して消費1 つ消費されたら消える
AWS サービスSNS, EventBridgeSQS
「注文が作成された」を通知 → 在庫、決済、通知が各自処理「画像をリサイズせよ」→ 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 はルールベースのフィルタリングで、条件に合致するターゲットにのみイベントを配信する。ただし「絞り込みができるのは EventBridge だけ」ではない。SNS も購読 (サブスクリプション) ごとにフィルターポリシーを設定でき、既定では全購読者が全メッセージを受け取る一方、ポリシーを付けた購読者は条件に合うメッセージだけを受け取る (Amazon SNS 開発者ガイド)。両者の差は絞り込みの宣言場所で、SNS は購読側に条件を持たせ、EventBridge はルール側にイベントパターンを持たせて 1 つのルールから Lambda・Step Functions・SQS といった異種のターゲットへ振り分ける。

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

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

メッセージの順序保証

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

サービス順序保証スループット用途
SNS + SQS (Standard)なし発行はアカウント + リージョン単位のクォータ内 (東京リージョンの既定は 1,500 メッセージ/秒)順序不問のイベント通知
SNS FIFO + SQS FIFOあり (メッセージグループ単位)メッセージグループあたり 300 メッセージ/秒 (トピック単位に切り替えた場合の既定は 3,000 メッセージ/秒または 20 MB/秒)順序が重要な処理
Kinesis Data Streamsあり (シャード単位)シャードあたり 1,000 レコード/秒かつ 1 MB/秒 (書き込み)高スループットのストリーム処理

数値は 2026 年 8 月時点の既定クォータで、引き上げ申請や高スループット FIFO の有効化で変わる。標準構成にも発行側のリージョン上限があるため、上限なしと考えないことが要点だ。また FIFO 経路は SNS 側と SQS 側の両方で制限を受ける。SQS の FIFO キューは、バッチ処理なしなら送信・受信・削除の各操作が 300 メッセージ/秒、バッチ処理ありなら 3,000 メッセージ/秒が既定であり、実効スループットは経路上の最も低い上限に張り付く。

よくある失敗パターン

購読者の障害の閉じ込め方を誤る

SNS から Lambda を直接呼び出す構成で Lambda がエラーを返すと、SNS はその購読の配信ポリシーに従ってリトライする。ここで誤解しやすいのは、リトライが他の購読者への配信を止めるわけではない点だ。配信もリトライも購読ごとに独立している。実害は別の形で出る。第 1 に、配信ポリシーを使い切ると SNS はリトライを止めてメッセージを破棄する。購読にデッドレターキューを付けていなければ、そのイベントは痕跡なく失われる。第 2 に、Lambda の同時実行数は既定でアカウントとリージョンあたり 1,000 という共有の枠であり、失敗した呼び出しの再試行が積み上がると同じリージョンの他の関数が枠を食われてスロットリングされる。SQS を挟めば、未処理のメッセージはキューに残り、リトライ回数と可視性タイムアウトを購読者側で制御できるため、障害の影響がその経路に閉じる。

メッセージの重複処理

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

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

この記事は役に立ちましたか?

関連用語

関連する記事