FOR LEARNERS学習中向け

Jコンテナとサーバーレス基盤段2構成層とは

Amazon SQS と Amazon SNS とは|キューとトピック、疎結合とファンアウト

Amazon SQS と Amazon SNS とは|キューとトピック、疎結合とファンアウト

Lambda で関数を書けるようになり、「注文が入ったら在庫を引き当て、メールを送り、集計にも回す」という処理を考え始めた。ところが、全部を1つの関数から順に呼ぶと、メールの送信が遅れただけで注文の受付まで止まってしまう。構成図には SQS や SNS が挟まっているけれど、キューとトピックの違いも、なぜ挟むと止まらなくなるのかも、まだ説明できない。この記事では、SQS と SNS を「受け手が取りに行く」と「送り手が配る」の違いから整理し、疎結合・標準と FIFO・可視性タイムアウト・デッドレターキュー・ファンアウトまでを、構成図を読める形にします。

この記事の結論

  • Amazon SQS はメッセージを貯めておき、受け手が取りに行って処理するキューのサービスです。
  • Amazon SNS はトピックに届いたメッセージを、購読しているすべての受け手へ配るサービスです。
  • 間に SQS や SNS を挟むと、送り手と受け手が互いの速さや障害に直接引きずられない疎結合の形になります。
  • SQS の標準キューは重複や順番の入れ替わりがありうるので、受け手の処理を何回実行しても結果が変わらない形にします。
  • 1つの出来事を複数の処理に確実に渡すときは、SNS から処理ごとの SQS キューへ配るファンアウトの形を使います。

Amazon SQS と Amazon SNS とは?何のために間に挟むのか

Amazon SQS(Amazon Simple Queue Service)は、メッセージを一時的に貯めておくキューのサービスです。Amazon SNS(Amazon Simple Notification Service)は、メッセージを複数の受け手に配るパブリッシュ/サブスクライブ(pub/sub)のサービスです。どちらも、アプリの部品どうしを直接つながずに、メッセージを介してやりとりさせるための道具です。

直接つなぐと、遅い方・壊れた方に引きずられる

注文を受ける処理が、在庫の引き当てを直接呼んでいるとします。在庫の処理が遅くなれば注文の受付も待たされ、在庫の処理が止まれば注文の受付も失敗します。これを密結合と呼びます。

間にキューを挟むと、注文を受ける処理は「在庫を引き当ててほしい」というメッセージをキューに置くだけで仕事を終えられます。在庫の処理は、自分の速さでキューからメッセージを取り出して処理します。在庫の処理が一時的に止まっても、メッセージはキューに残り、復旧してから処理されます。このように、互いの速さや障害が直接波及しない形を疎結合と呼びます。

たとえるなら、整理券箱と館内放送

  • SQS は受付の整理券箱です。お客さん(送り手)は用件を書いた券を箱に入れて帰れます。係(受け手)は手が空いたら1枚ずつ取って処理します。係が増えれば、同じ箱から並行して取っていけます。
  • SNS は館内放送です。1回流せば、放送を聞いている全員(購読者)に同時に届きます。誰が聞いているかを、放送する側は知らなくてかまいません。

たとえを正確な言葉に戻すと、整理券箱がキュー、券がメッセージ、係がコンシューマー(受け手)です。放送の系統がトピック、聞いている人がサブスクリプション(購読)です。

READ ALSO — 学習中向け・段2 構成 AWS Lambda とは何か|イベントで動く関数と、実行時間などの制約を EC2・コンテナと比べて理解する

キューとトピックはどう違うのか

PULL OR PUSHキューとトピック

SQS は取りに行く、SNS は配る

Amazon SQS(キュー)

整理券箱

  • メッセージを貯めておく
  • 受け手が取りに行く
  • 1つのメッセージは1つの受け手が処理する

Amazon SNS(トピック)

館内放送

  • 届いたらすぐ配る
  • 購読者へ送り届ける
  • 同じメッセージが購読者全員に届く
出典: AWS Decision Guides(Amazon SQS, Amazon SNS, or Amazon EventBridge?)
観点 Amazon SQS(キュー) Amazon SNS(トピック)
受け渡しの向き 受け手が取りに行く(プル) 送り手の側から受け手へ配る(プッシュ)
1つのメッセージを誰が受けるか 取り出した1つの受け手が処理する 購読しているすべての受け手に届く
メッセージを貯めるか 貯める(既定で4日、最長14日まで設定できる) 受け手が取りに来るまで貯める場所ではない(届かなければ再試行する)
主な受け手 EC2・ECS のタスク・Lambda など、取りに来る処理 SQS・Lambda・HTTP/S・メール・SMS・モバイルプッシュ
向いている場面 仕事を渡す、処理の速さの差を吸収する 1つの出来事を複数の受け手に知らせる

AWS の意思決定ガイドも、SQS はメッセージを取りに行く受け手(EC2 や Lambda など)のため、SNS は多様な受け手へ一斉に配るため、と役割を分けて説明しています。

ここで押さえたいのは、SQS は「仕事を1つずつ確実に渡す」、SNS は「出来事を全員に知らせる」という役割の違いです。SNS の受け手に SQS のキューを指定できるので、両者は対立するものではなく、組み合わせて使えます(後の章のファンアウト)。

CHECK 1ここまでの確認

SQS と SNS の受け渡しの違いとして正しいのはどれ?

答えと解説

答え: 1. SQS は受け手がキューから取りに行き、SNS は購読している受け手へ配る

SQS はメッセージを貯めておき、受け手(コンシューマー)が取りに行く(プル)形です。SNS はトピックに届いたメッセージを、購読しているすべての受け手へ配る(プッシュ)形です。「キューとトピックはどう違うのか」の章を読み直してください。

SQS の仕組み(標準と FIFO、可視性タイムアウト、デッドレターキュー)とは

SQS を使いこなすには、メッセージがキューの中でどう扱われるかを知る必要があります。1つのメッセージの旅を追います。

LIFE OF A MESSAGEメッセージの旅

受け取っても消えない。処理を終えた受け手が削除する

  1. 送信

    送り手がキューへ

  2. キューで待つ

    既定で4日保持

  3. 受信

    一定時間見えなくなる

  4. 処理

    時間内に終える

  5. 削除

    受け手が消す

削除されないまま可視性タイムアウトが切れると、再び見えるようになる。出典: Amazon SQS デベロッパーガイド

受け取っても消えない。削除するのは受け手

SQS では、受け手がメッセージを受信しただけではキューから消えません。受け手が処理を終えてから、自分で削除します。受信してから削除するまでの間、そのメッセージはほかの受け手から見えなくなります。この見えない時間が可視性タイムアウトです。

公式ドキュメントによると、可視性タイムアウトの既定は30秒で、最長12時間まで設定できます。処理にかかる時間より短く設定すると、処理中のメッセージが再び見えるようになり、別の受け手がもう一度処理してしまいます。処理が長くなる場合は、処理の途中で可視性タイムアウトを延ばすこともできます。

標準キューと FIFO キュー

観点 標準キュー FIFO キュー
届く回数 少なくとも1回(まれに重複する) 1回だけ処理される(重複を排除する)
順番 できるだけ送った順(入れ替わることがある) 送った順を厳密に保つ(メッセージグループごと)
処理できる量 大きい 標準より上限が小さい(上限は公式ページで確認)
受け手に求めること 重複しても結果が変わらない(冪等な)処理 順番の単位(メッセージグループ ID)を決める

標準キューは、メッセージの写しを複数のサーバーに持つ仕組みのため、同じメッセージが2回以上届いたり、順番が前後したりすることがあります。公式ドキュメントは、受け手の処理を冪等(同じメッセージを何度処理しても結果が変わらない)にすることを勧めています。支払いの確定のように、順番が変わると困る・二重に実行すると困る処理には FIFO キューを選びます。

処理できないメッセージはデッドレターキューへ

形式が壊れているなど、何度処理しても失敗するメッセージがあると、受信 → 失敗 → 再び見える、を繰り返してキューに居座ります。これを隔離するのがデッドレターキュー(DLQ)です。元のキューに「受信された回数が maxReceiveCount を超えたら、このキューへ移す」という設定(リドライブポリシー)を付けます。

デッドレターキューは、元のキューと同じ種類(標準なら標準、FIFO なら FIFO)で作ります。移ったメッセージは原因を調べてから、元のキューに戻して処理し直せます。公式ドキュメントは、デッドレターキューの保持期間を元のキューより長くしておくことを勧めています。

CHECK 2ここまでの確認

SQS で受け取ったメッセージを、可視性タイムアウトの間に削除しなかったらどうなる?

答えと解説

答え: 2. メッセージはキューの中で再び見えるようになり、別の受け手が受け取れる

受け取ったメッセージは、可視性タイムアウトの間だけほかの受け手から見えなくなります。その間に削除されなければ再び見えるようになり、もう一度処理されます。処理時間より短く設定すると、同じメッセージが二重に処理される原因になります。

CHECK 3ここまでの確認

SQS の標準キューを使うとき、受け手の処理で気をつけることはどれ?

答えと解説

答え: 1. 同じメッセージが2回以上届いても結果が変わらないようにする

標準キューは「少なくとも1回」の配信で、まれに同じメッセージが複数回届き、順番も前後することがあります。同じメッセージを何回処理しても結果が変わらない(冪等な)処理にしておきます。順番と重複の排除が要るなら FIFO キューを選びます。

CHECK 4ここまでの確認

何度処理しても失敗するメッセージを、ほかのメッセージの処理を妨げないように隔離する仕組みはどれ?

答えと解説

答え: 2. デッドレターキュー

デッドレターキューは、決めた回数(maxReceiveCount)を超えて受信されたメッセージを移しておく別のキューです。原因を調べてから、元のキューに戻して処理し直せます。

ファンアウトとは?SNS から複数の SQS へ配る形

注文が1件入ったら、在庫の引き当て・確認メールの送信・売上の集計の3つを、それぞれ独立に処理したいとします。注文を受ける処理が3つのキューに別々に送ることもできますが、受け手が増えるたびに送り手を直すことになります。

そこで、注文を受ける処理は SNS のトピックに1回だけ発行し、トピックを処理ごとの SQS キューが購読する形にします。これをファンアウトと呼びます。

  • 送り手は、誰が受け取るかを知らずに済みます。受け手を足すときは、キューを作ってトピックを購読させるだけです。
  • 受け手ごとにキューがあるので、1つの処理が遅れても止まっても、ほかの処理はそれぞれのキューから進められます。
  • それぞれのキューにデッドレターキューを付けて、処理ごとに失敗を扱えます。

受け取るメッセージを絞るフィルターポリシー

すべての受け手が、すべてのメッセージを要るとは限りません。SNS では、サブスクリプションごとにフィルターポリシーを付けて、メッセージの属性や本文の値が条件に合うものだけを受け取れます。

FILTER POLICY受け取るものを絞る

購読ごとのフィルターポリシーが、届くメッセージを選ぶ

SNS のサブスクリプション(購読ごとの条件)

  • 在庫在庫用のキュー すべて受ける条件なし
  • 集計集計用のキュー すべて受ける条件なし
  • 高額審査用のキュー 高額だけ金額が条件に合う
  • 通常審査用のキュー 届かない条件に合わない
条件はメッセージの属性か本文の値で書く。出典: Amazon SNS デベロッパーガイド(message filtering)

順番と重複の排除が要る場合は、SNS の FIFO トピックと SQS の FIFO キューを組み合わせます。FIFO トピックでもフィルターポリシーは使えます。

READ ALSO — プロフェッショナル向け・段4 設計 トレードオフの考え方|「なぜそのサービスか」を根拠つきで説明する型と、Well-Architected の6本柱の使い方

EventBridge はどこに位置づくのか

SQS と SNS の話をすると、Amazon EventBridge がよく並んで出てきます。EventBridge は、イベントを受け取ってルールで振り分けるイベントバスのサービスです。AWS のサービスや SaaS から届くイベント、自分のアプリが送るイベントを受け取り、ルールに書いた条件(イベントパターン)に合うものを、Lambda・SQS・SNS などのターゲットへ送ります。

観点 SQS SNS EventBridge
形 キュー トピック(pub/sub) イベントバス+ルール
受け渡し 受け手が取りに行く 購読者へ配る ルールに合うターゲットへ送る
振り分け しない(キューに入れた順に取り出す) フィルターポリシーで絞る イベントの中身のパターンで細かく振り分ける
よく使う場面 仕事を渡す、負荷の山をならす 一斉に知らせる、ファンアウト AWS のサービスの状態変化に反応する、定期実行、アカウントをまたぐ

AWS の意思決定ガイドは、3つとも部品どうしを疎結合にするためのサービスだとしたうえで、SQS は処理の非同期化と負荷の吸収、SNS はファンアウトと一斉の通知、EventBridge はイベント駆動の構成とアカウントをまたいだイベントの共有、と得意な場面を分けています。

まず SQS と SNS で「渡す」と「配る」を掴み、AWS のサービスの出来事に反応したくなったら EventBridge を学ぶ、という順で読むと迷いにくくなります。EventBridge の詳しい仕組みは、同じ領域の別の記事で扱います。

まとめ

  • SQS はキュー。受け手が取りに行き、1つのメッセージを1つの受け手が処理します。
  • SNS はトピック。購読しているすべての受け手へ同じメッセージを配ります。
  • 間に挟むと、送り手と受け手の速さの差や障害が直接波及しない疎結合の形になります。
  • SQS では、可視性タイムアウトを処理時間に合わせ、標準キューなら冪等な処理にし、失敗し続けるメッセージはデッドレターキューへ隔離します。
  • 1つの出来事を複数の処理に確実に渡すなら、SNS から処理ごとの SQS へのファンアウトを使います。

キューの先で動く処理は、Lambda のほかに ECS や EKS のコンテナのこともあります。次は、コンテナを動かす2つの選択肢を比べて、どちらを選ぶかを考えます。

参照ソース

SCOREこの記事の確認テスト

0/4問 正解

各章の「ここまでの確認」に答えると、ここに集まります。結果はこの端末のブラウザにだけ残り、サーバには送りません。

PRACTICEこの記事の論点を練習問題で確かめる

この記事が扱うサービスの問題だけを続けて解けます。練習問題は Google でログインした人が使えます(練習問題の一覧)。

HAND IT OVER人に渡すなら

一言で説明するなら

SQS は受付の整理券箱で、手の空いた係が1枚ずつ取って処理します。SNS は館内放送で、1回流せば聞いている全員に同時に届きます。

FAQよくある質問

SQS と SNS はどちらを使えばよいですか?

1つの仕事を1つの処理に確実に渡したい、処理の速さの差を吸収したいなら SQS。1つの出来事を複数の受け手に同時に知らせたいなら SNS です。複数の受け手それぞれに確実に処理させたいときは、SNS から処理ごとの SQS キューへ配るファンアウトの形で両方を組み合わせます。

SNS から SQS へのファンアウトと EventBridge は、どう使い分けますか?

同じメッセージを決まった受け手へ配るだけなら SNS から SQS へのファンアウトで足ります。AWS のサービスや SaaS から届くイベントを、中身の条件で細かく振り分けたり、ほかのアカウントのイベントバスへ送ったりしたいなら EventBridge が候補になります。どちらを選ぶかの考え方は、AWS の意思決定ガイド(SQS・SNS・EventBridge の比較)にまとまっています。

SQS と SNS の料金はどうかかりますか?

どちらも、リクエストや配信の量に応じた従量課金です。無料で使える量や単価はサービスごとに決まっていて改定されることがあるので、Amazon SQS と Amazon SNS の料金ページで確認してください。

SAME TRACK同じ領域の記事

ECS のタスク定義を設計する|サイズ・ロール・設定の渡し方を「1つのタスクに何を持たせるか」で決める
ECS のタスク定義を設計する|サイズ・ロール・設定の渡し方を「1つのタスクに何を持たせるか」で決める 段2 構成設計
ECS のタスクが止まる・デプロイが進まないときの調べ方|停止理由・サービスイベント・サーキットブレーカーを順に見る運用
ECS のタスクが止まる・デプロイが進まないときの調べ方|停止理由・サービスイベント・サーキットブレーカーを順に見る運用 段2 構成運用
Amazon EventBridge とは何か|イベントバス・ルール・ターゲットと SNS・SQS との使い分け
Amazon EventBridge とは何か|イベントバス・ルール・ターゲットと SNS・SQS との使い分け 段2 構成とは