SQS と SNS

Amazon SQS(Simple Queue Service)はメッセージを一時的に溜めておくキュー、Amazon SNS(Simple Notification Service)は 1 つのメッセージを複数の宛先へ一斉に届ける通知サービスです。SAA では、システム同士を「疎結合」にして障害や急な負荷に強くする設計で頻出します。

ひとことで言うと: SQS は「受付の順番待ちの列」、SNS は「一斉送信のメーリングリスト」です。

たとえるなら、SQS は注文票を置いておく受付トレイで、厨房が忙しくても注文票はトレイに溜まり、手が空いた順に処理されます。SNS は、1 通送れば登録している全員に届く社内一斉連絡です。

このページで押さえる論点

疎結合とキューイング・メッセージングの考え方

2 つのシステムが直接呼び出し合う形を密結合と呼びます。相手が止まっていたり処理が追いつかなかったりすると、呼び出した側まで失敗します。間に SQS を挟むと、送信側はメッセージをキューに置くだけで済み、受信側は自分のペースで取り出して処理できます。これが疎結合です。

SAA の試験ガイドでは「疎結合を実現するために必要な AWS のサービスを決定する」「コンポーネントを個別にスケールできるようにワークロードを疎結合にする」ことが求められます。キューを挟むと、送信側(プロデューサー)と受信側(コンシューマー)の台数を別々に増減できます。メッセージングには大きく 2 つの型があります。

再生型アニメ図解

密結合と疎結合の比較

密結合(直接呼び出し) 注文 在庫 ✕ 停止中 ✕ 呼び出し失敗 疎結合(SQS を挟む) 注文 SQS 在庫 ✕ 停止中 ✓ 復旧 ✓ 受付完了

※簡略化しています: 在庫サービスはキューを定期的に確認(ポーリング)してメッセージを取り出しますが、図では取り出しの瞬間だけを示しています。

SQS の基本動作

SQS はコンシューマーがキューに「メッセージはありますか」と問い合わせて取り出すプル型(ポーリング)のサービスです。送られたメッセージは、SQS が複数のアベイラビリティーゾーン(AZ)に冗長に保存します。

可視性タイムアウト

コンシューマーがメッセージを受信しても、メッセージはすぐには消えません。キューに残ったまま、一定時間だけほかのコンシューマーから見えなくなります。この時間が可視性タイムアウトです(既定 30 秒、最大 12 時間)。処理が終わったらコンシューマーがメッセージを削除します。削除しないままタイムアウトを過ぎると、メッセージは再び見えるようになり、別のコンシューマーが同じメッセージを処理してしまいます。そのため、可視性タイムアウトは処理にかかる最大時間に合わせて設定します。処理が長引く場合は ChangeMessageVisibility で途中から延長できます。

ショートポーリングとロングポーリング

既定のショートポーリングは、メッセージが見つからなくてもすぐに空の応答を返します。ロングポーリングは、メッセージが届くまで最大 20 秒待ってから応答します。空の応答が減るので、問い合わせ回数に応じてかかる SQS のコストを下げられます。

デッドレターキュー(DLQ)

何度処理しても失敗するメッセージ(形式が壊れているなど)がキューに残り続けると、ほかのメッセージの処理を邪魔します。そこで、受信回数の上限(maxReceiveCount)を超えたメッセージを別のキュー(デッドレターキュー)へ移し、あとで原因を調べます。原因を直したら、DLQ から元のキューへ戻して再処理(リドライブ)できます。

SQS の設定値と暗号化

項目値試験での使いどころ
メッセージ保持期間既定 4 日(最小 60 秒、最大 14 日)受信側が長期間止まっても、この期間内に復旧すれば処理を再開できる。14 日を超えて保持したい要件には SQS だけでは応えられない
最大メッセージサイズ1 MiB(1,048,576 バイト)それより大きいデータは本体を S3 に置き、SQS にはその参照を送る(SQS 拡張クライアントライブラリ)
遅延(遅延キュー・メッセージタイマー)既定 0 秒、最大 15 分送ったメッセージを一定時間コンシューマーに見せたくない
可視性タイムアウト既定 30 秒(最小 0 秒、最大 12 時間)二重処理を防ぐため処理時間に合わせる
ロングポーリングの待機時間最大 20 秒空の応答を減らしてコストを下げる
バッチ送信1 リクエストに最大 10 メッセージAPI 呼び出し回数を減らしてスループットを上げる

遅延キューは、キューに入れたメッセージを一定時間(最大 15 分)見えなくする設定です。可視性タイムアウトと似ていますが、見えなくなるタイミングが違います。遅延キューは「キューに入った直後」、可視性タイムアウトは「受信された後」に見えなくなります。キュー全体ではなくメッセージごとに遅延させたいときはメッセージタイマーを使います。

暗号化: 保管中のメッセージは、サーバー側暗号化(SSE)で暗号化できます。鍵の管理方法は、SQS が管理する鍵を使う SSE-SQS と、AWS KMS の鍵を使う SSE-KMS の 2 種類です。暗号化されるのはメッセージ本文で、キュー名やメッセージ ID などのメタデータは暗号化されません。また、暗号化を有効にする前からキューにあったメッセージは暗号化されません。SSE を有効にしたキューへのリクエストは HTTPS(転送中の暗号化)を使う必要があります。

標準キューと FIFO キュー

項目標準キューFIFO キュー
配信回数少なくとも 1 回(まれに重複あり)1 回だけ(重複を排除)
順序ベストエフォート(入れ替わることがある)送った順(First-In-First-Out)。メッセージグループごとに保証
処理量ほぼ無制限高スループットモードでない場合、API アクションごとに毎秒 300 件。10 件ずつのバッチで毎秒 3,000 メッセージ。高スループットモードにすると上限が上がる
向いている場面大量の処理を並列でさばく決済や在庫の更新など、順序と重複が問題になる処理

標準キューは重複や順序の入れ替わりが起こりうるので、受信側で「同じメッセージを 2 回処理しても結果が変わらない」作りにしておく必要があります。FIFO キューでは次の 2 つが試験で問われます。

キューの滞留に合わせたスケーリング

キューに入るメッセージが、受信側の処理能力より多ければ滞留は増え、少なければ減ります。受信側(コンシューマー)の台数を増やすと処理能力が上がります。

操作できるシミュレーター

送信数とコンシューマー数でキューの滞留を見る

「▶ スタート」で 1 秒ずつ時間が進みます。コンシューマー 1 台は毎秒 10 件を処理します。

送信側 SQS 受信側

※簡略化しています: コンシューマー 1 台は毎秒 10 件を一定の速さで処理すると仮定しています。可視性タイムアウト、処理失敗時の再試行、デッドレターキュー、SQS 側の上限は省略しています。バーは 1,000 件で満杯表示です。

コンシューマーを EC2 の Auto Scaling グループで動かす場合、キューのメッセージ数をそのまま指標にすると、台数と比例しないので適切に増減できないことがあります。AWS はインスタンスあたりのバックログ(キューのメッセージ数 ÷ 稼働中のインスタンス数)を指標にしたターゲット追跡スケーリングを案内しています。目標値は「許容できる最大の待ち時間 ÷ 1 件あたりの平均処理時間」で決めます。たとえば許容 10 秒・1 件 0.1 秒なら目標は 1 台あたり 100 件です。10 台で 1,500 件溜まっていれば 1 台あたり 150 件なので、5 台増やして 15 台にします。

図では省略している可視性タイムアウト・再試行・デッドレターキューは「SQS の基本動作」、処理量の上限は「標準キューと FIFO キュー」で説明しています。

SNS のパブリッシュ/サブスクライブとファンアウト

SNS では、送り手がトピック(話題ごとの配信窓口)にメッセージを発行(パブリッシュ)し、トピックをサブスクライブ(購読登録)している宛先すべてに届けます。SQS と違い、SNS から宛先へ押し出すプッシュ型です。宛先には次のものを指定できます。

SQS キューを宛先にすると、各システムが自分のペースで確実に処理できます。これが SNS + SQS のファンアウトです。

再生型アニメ図解

1 通のメッセージが複数の SQS に配られる

注文 SNS SQS SQS SQS 在庫 配送 メール

※簡略化しています: 配信の失敗と再試行、宛先ごとに受け取るメッセージを絞り込むフィルターポリシーは省略しています。

フィルターポリシー

既定では、トピックの全購読者がすべてのメッセージを受け取ります。サブスクリプションにフィルターポリシー(JSON で書く受信条件)を設定すると、条件に合うメッセージだけを受け取れます。条件はメッセージ属性か、JSON 形式のメッセージ本文に対して書けます。たとえば「注文種別が返品のメッセージだけを返品処理用キューに届ける」ことが、送信側を変えずに実現できます。

配信の失敗と FIFO トピック

EventBridge・Kinesis Data Streams・Amazon MQ・Step Functions との使い分け

サービス仕組み選ぶ場面
Amazon SQSキュー。1 件を 1 つのコンシューマーが処理して削除(プル型)処理の平準化、非同期処理、後段の障害からの保護
Amazon SNSトピックの全購読者へ配信(プッシュ型)1 つのメッセージを複数の宛先へ同時に配る、メール・SMS 通知
Amazon EventBridgeイベントバスがルール(イベントパターン)に合うイベントをターゲットへ振り分ける。EventBridge スケジューラで cron 式・rate 式の定期実行も可能AWS サービスや SaaS、自社アプリのイベントを内容に応じて振り分けるイベント駆動型の構成
Amazon Kinesis Data Streamsストリーム。データをシャードに分けて保持し、複数のアプリが同じデータを同時に独立して読める。保持期間は既定 24 時間、最大 365 日クリックストリームやログなど大量データのリアルタイム処理、同じデータを複数の用途で読む・読み直す
Amazon MQApache ActiveMQ・RabbitMQ のマネージドなメッセージブローカー業界標準のプロトコルを使う既存アプリを、メッセージングのコードを書き換えずに移行する
AWS Step Functions複数の処理をワークフローとして定義し、順番・分岐・エラー処理を管理複数ステップの処理を順序どおりに実行し、途中の失敗も扱いたい

見分け方の目安: 「後で確実に処理したい」なら SQS、「複数に同時に配りたい」なら SNS、「イベントの中身で行き先を変えたい」なら EventBridge、「大量のデータを流し続け、複数のアプリで読む・読み直す」なら Kinesis Data Streams です。SQS では受信側が削除したメッセージは読み直せませんが、Kinesis Data Streams では保持期間内なら何度でも読めます。

問題文のキーワード → 選ぶべき答え

問題文の言い回し選ぶべき答えと理由
「急なアクセス増を吸収したい」「後段が停止しても注文を失いたくない」SQS で疎結合。メッセージがキューに溜まり、後段は自分のペースで処理できる
「送信した順序どおりに」「重複なく 1 回だけ処理」SQS FIFO キュー。標準キューは順序も 1 回配信も保証しない
「1 つのイベントを複数のシステムで並行・独立に処理」SNS + SQS のファンアウト。宛先ごとのキューで独立して処理できる
「特定の条件のメッセージだけを受け取りたい」SNS のサブスクリプションフィルターポリシー。送信側を変えずに宛先ごとに絞り込める
「空の応答を減らしてコストを削減」ロングポーリング(最大 20 秒待つ)
「同じメッセージが複数のコンシューマーで二重に処理される」可視性タイムアウトを処理時間より長くする
「何度も処理に失敗するメッセージを隔離して調査」デッドレターキュー(maxReceiveCount を超えたら移動)
「キューに入れたメッセージの処理開始を数分遅らせたい」遅延キュー(最大 15 分)。メッセージごとならメッセージタイマー
「1 MiB を超えるメッセージを扱いたい」本体を S3 に置き、SQS には参照を送る(拡張クライアントライブラリ)
「キューの滞留に応じてワーカーの台数を増減」インスタンスあたりのバックログを指標にしたターゲット追跡スケーリング
「リアルタイムのストリーミングデータを複数のアプリで読む・再処理する」Kinesis Data Streams。保持期間内なら同じデータを何度でも読める
「AWS サービスや SaaS のイベントをルールで振り分け」「定期実行」EventBridge(ルール、スケジューラ)
「既存の ActiveMQ/RabbitMQ アプリをコードを変えずに移行」Amazon MQ
「保管中のメッセージを KMS の鍵で暗号化」SQS の SSE-KMS

引っかけポイント

まとめ: SAA 試験で押さえるポイント

確認問題

参考リンク

AWS 公式ドキュメント(外部サイトが開きます)。本文の数値はこれらで確認しています。