ファンアウト

1 つのイベントを複数のコンシューマーに同時配信するメッセージングパターン

アーキテクチャイベント駆動

ファンアウトとは

ファンアウト (Fan-Out) は、1 つのイベントを複数のコンシューマーに同時配信するメッセージングパターンである。SNS + SQS の組み合わせが AWS での代表的な実装。

ファンアウトの構造

ファンアウトの構造を図で示す。

注文サービス → SNS トピック → SQS (在庫サービス)
                            → SQS (通知サービス)
                            → SQS (分析サービス)
                            → Lambda (監査ログ)

プロデューサーは 1 つのトピックに発行するだけ。コンシューマーの追加・削除はプロデューサーに影響しない。

SNS vs EventBridge

SNS と EventBridge の違いを以下にまとめる。

観点SNSEventBridge
フィルタリングメッセージ属性 (既定) / 本文も選べるイベント内容のパターンマッチ
ターゲットSQS, Lambda, HTTP(S), メール, SMS, モバイルプッシュ多数の AWS サービス + API 送信先
順序保証FIFO トピックで可 (キューを宛先にする場合)なし
スキーマなしSchema Registry

SNS のフィルタリングは既定でメッセージ属性を見るが、サブスクリプションの FilterPolicyScopeMessageBody にすればメッセージ本文の中身でも振り分けられる。属性を付け直すためにプロデューサーを改造する必要は無い。使い分けの目安は、自分が出したイベントを自分の購読者へ配るだけなら SNS、他サービスや外部サービス由来のイベントを条件で仕分けて多様な宛先へ流すなら EventBridge。

ファンアウトとテールレイテンシ

ファンアウトとテールレイテンシを図で示す。

1 リクエストが 10 の Lambda を並列呼び出しし、全部の応答を待つ:
  各呼び出しが 100ms を超える確率 = 1% (P99 = 100ms のため)
  10 個のどれかが 100ms を超える確率 = 1 - 0.99^10 ≈ 9.6%
→ 全体の所要時間は「一番遅い 1 つ」で決まるので、
   呼び出し先が増えるほど遅い側を引く確率が上がる
→ 全部の応答を待つ必要が無い処理は
   非同期ファンアウト (SNS/SQS) へ寄せて影響を分離

この計算は各呼び出しの遅さが互いに無関係な場合の目安である。実際には共通の下流 (同じデータベース・同じ外部 API) を叩いていると遅さが同時に起きるため、悪化はこれより急になる。並列度を上げる前に、呼び出し先が資源を共有していないかを確認しておきたい。

ファンイン (逆パターン)

ファンイン (逆パターン) を図で示す。

複数のソース → 1 つの集約先

S3 バケット A → Lambda → DynamoDB
S3 バケット B → Lambda → DynamoDB
S3 バケット C → Lambda → DynamoDB

ファンアウトの注意点

ファンアウトの注意点を以下にまとめる。

注意点対策
メッセージの順序SNS FIFO トピック + SQS FIFO キューで保証
重複配信冪等性を確保
コンシューマーの障害DLQ で失敗メッセージを保持
コストコンシューマー数 × メッセージ数

順序を守りたいなら発行側のトピックから FIFO にする必要がある。標準トピックは配信順序を保証しないので、下流のキューだけ FIFO にしても元の順序は復元できない。ただし FIFO トピックにはメール・SMS・HTTP(S) といった宛先を購読させられず、Lambda へ流すときも直接ではなく SQS を挟む形になる。順序が本当に要る経路だけを FIFO にして、残りは標準トピックに寄せるのが扱いやすい。

全体像を把握するには関連書籍も有用。

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

関連用語

関連する記事