Amazon SNS で構築する Pub/Sub メッセージング - ファンアウトパターンとフィルタリング

SNS によるトピックベースのメッセージング、サブスクリプションフィルター、SQS ファンアウトパターンを解説します。

SNS の概要

SNS は Pub/Sub メッセージングサービスで、1 トピックあたり最大 1,250 万サブスクリプションをサポートし、メッセージサイズは最大 256 KB です。パブリッシャーがトピックにメッセージを送信し、トピックをサブスクライブしている全サブスクライバーにメッセージが配信されます。SQS がポイントツーポイントのキューイングであるのに対し、SNS は 1 対多のファンアウトを実現します。Standard トピックはほぼ無制限のスループットでベストエフォート順序配信を行い、FIFO トピックは秒間 300 メッセージ (バッチ使用時は 3,000) の厳密な順序保証と重複排除を提供します。サブスクリプションプロトコルとして SQS、Lambda、HTTP/S、Email、SMS、Kinesis Data Firehose に対応し、1 つのトピックから異なるプロトコルの複数サブスクライバーに同時配信できます。

ファンアウトとフィルタリング

SNS + SQS ファンアウトパターンでは、SNS トピックに複数の SQS キューをサブスクライブし、1 つのメッセージを複数のコンシューマーに並行配信します。注文イベントを在庫管理キュー、配送キュー、通知キューに同時配信するパターンが典型的です。サブスクリプションフィルターポリシーはメッセージ属性に基づくフィルタリングで、サブスクライバーが必要なメッセージのみを受信します。フィルターポリシーは MessageAttributes (デフォルト) または MessageBody をスコープとして設定でき、文字列の完全一致、プレフィックス一致、数値範囲、exists 演算子を組み合わせた複合条件を定義できます。FIFO トピックはメッセージグループ ID で順序を制御し、同一グループ内のメッセージは厳密に FIFO で配信されます。異なるグループ間は独立して並行配信されるため、スループットを確保しながら必要な部分のみ順序を保証する設計が可能です。

デッドレターキューとリトライ

SNS のサブスクリプションにデッドレターキュー (DLQ) を設定すると、配信に失敗したメッセージが SQS キューに退避されます。 HTTP/S エンドポイントへの配信はリトライポリシー (即時リトライ、バックオフリトライ) で再試行回数と間隔を制御します。HTTP/S 配信のリトライは 3 フェーズに分かれ、即時リトライ (1 回)、バックオフフェーズ (10 回、指数バックオフ)、バックオフ後 (38 回、20 秒間隔) の合計 49 回のリトライを行います。 Lambda サブスクリプションは Lambda の非同期呼び出しのリトライポリシーに従います。配信ステータスログを CloudWatch Logs に出力し、配信の成功率とエラー原因を分析できます。配信ステータスログには成功と失敗のサンプリング率を個別に設定でき、コスト管理のために成功ログのサンプリングを 10% 程度に抑える運用が一般的です。クロスアカウントのトピックアクセスはリソースベースポリシーで制御します。 SNS について体系的に学びたい方は、関連書籍 (Amazon)も参考になります。

設計のベストプラクティスと落とし穴

メッセージ属性の設計はフィルタリング効率に直結します。フィルタリングに使う属性は MessageAttributes に含め、ペイロード本体のパースをサブスクライバー側で不要にする設計を推奨します。Standard トピックではメッセージの重複配信 (at-least-once) が発生するため、コンシューマーは冪等性を確保する必要があります。Large message payload (256 KB 超) を扱う場合は、S3 にペイロードを格納し SNS メッセージには S3 参照のみを含める Extended Client Library パターンを採用します。FIFO トピックでは MessageDeduplicationId の設計が重要で、コンテンツベース重複排除を有効にすると本文ハッシュで自動判定しますが、意図しない重複排除に注意が必要です。暗号化には SSE-SNS (AWS 管理キー) と SSE-KMS (CMK) の 2 方式があり、クロスアカウントの場合は CMK のキーポリシーで配信先アカウントに復号権限を付与する設計が必要です。

EventBridge との使い分け

SNS と EventBridge はどちらもイベント駆動アーキテクチャの基盤ですが、適用領域が異なります。SNS は高スループット (Standard トピックでほぼ無制限) かつシンプルな属性フィルタリングで十分なケースに適しています。EventBridge はイベントの構造 (JSON ボディの任意のフィールド) に対する高度なパターンマッチ、スケジュールトリガー、SaaS 統合 (Shopify、Zendesk など) が必要なケースに適しています。料金面では SNS の SQS 配信が無料であるのに対し、EventBridge はイベントごとに課金されるため、同一イベントを多数のターゲットにファンアウトする純粋な Pub/Sub ワークロードでは SNS が低コストです。一方、少数のルールで複雑なルーティングを行うケースでは EventBridge のルールベース設計が保守性に優れます。両者を組み合わせ、EventBridge でルーティング後に SNS でファンアウトする構成も有効です。

SNS のコスト管理

SNS のコストはパブリッシュ数と配信先のプロトコルで決まります。SQS への配信は無料のため、SNS → SQS → Lambda のパターンは SNS → Lambda の直接配信と比較してコスト面で有利な場合があります。HTTP/S 配信は 10 万件あたり 0.06 ドル、SMS は送信先国によって大きく異なります (米国 0.00645 ドル/件、日本 0.07086 ドル/件)。メッセージフィルタリングで不要な配信を削減し、Lambda の実行回数を最適化します。大量のメッセージを処理する場合、メッセージのバッチ化 (1 メッセージに複数イベントを含める) でパブリッシュ数を削減できます。FIFO トピックは Standard の 2 倍の料金 (100 万リクエストあたり 0.50 ドル) のため、順序保証が不要な部分には Standard を使い分けてコストを抑えます。

まとめ

SNS は Pub/Sub メッセージングでファンアウトパターンを実現するサービスです。サブスクリプションフィルターで属性に基づく効率的なメッセージルーティングを行い、DLQ で配信失敗メッセージを確実に捕捉します。SQS への配信は無料のため、SNS → SQS → Lambda のパターンでコスト効率の高い非同期処理を構築し、FIFO トピックで必要箇所のみ順序保証を適用します。EventBridge との使い分けにより、スループット要件とルーティング複雑度に応じた最適なイベント駆動アーキテクチャを設計できます。