AWS SQS VISUALIZER

AWS SQS

分散システム間のメッセージを安全にキューイングするフルマネージドメッセージキューサービス

シナリオ
メッセージが送られてから処理されるまでの流れと、処理に失敗したらどうなるかを見てみます
ステップ1 / 4
ステップ
SQS の登場人物は3つだけ — 送る人・キュー・受け取る人
SQS は「送る人(プロデューサー)」「メッセージを一時的に預かるキュー」「受け取って処理する人(コンシューマー)」の3つで成り立っています。キューが間に入ることで、送る側と受け取る側を分離でき、片方が止まっても相手に影響しません。
ARCHITECTURE DIAGRAM
プロデューサー → キュー → コンシューマーの基本フローと可視性タイムアウト
STEP 1
CODE VIEW
── SQS メッセージフロー ──
 
$ aws sqs create-queue \
--queue-name MyQueue
 
{
"QueueUrl": "https://sqs.ap-northeast-1.amazonaws.com/123456789/MyQueue"
}
 
◎ プロデューサー → SQSキュー → コンシューマー の3者構造
プロデューサー
SQS キュー
コンシューマー
Dead Letter Queue
メッセージ
解説

📌
SQS とは何か

Amazon SQS(Simple Queue Service)は、フルマネージドのメッセージキューサービスです。アプリケーション間でメッセージを非同期にやり取りすることで、サービス間を疎結合にできます。現実世界に例えると「郵便受け」のようなもので、送信者(プロデューサー)は受信者(コンシューマー)の状態を気にせずメッセージを投函でき、受信者は自分のペースで処理できます。

SQS には2つのキュータイプがあります。Standard キューは「少なくとも1回の配信」を保証し、ほぼ無制限のスループットを提供しますが、メッセージの順序は保証されません。FIFO キューは「正確に1回の処理」と「メッセージの順序保証」を提供しますが、秒間300メッセージ(バッチで3,000)の制限があります。SAA 試験では、ユースケースに応じてどちらを選ぶかが問われます。

SQS の主なユースケースは、マイクロサービス間の通信、非同期処理(注文処理、画像変換など)、ピーク負荷の平滑化(バッファリング)、ファンアウトパターン(SNS + SQS の組み合わせ)などです。メッセージの保持期間はデフォルト4日、最大14日で、メッセージサイズは最大256KBです。それ以上のデータを扱う場合は、Extended Client Library を使って S3 にデータを格納し、SQS にはポインタだけを送信します。

Producerメッセージ送信SQS QueueメッセージバッファConsumerメッセージ処理疎結合: Producer と Consumer は互いの状態を知らない
## SQS キューの作成
$ aws sqs create-queue \
--queue-name MyQueue \
--attributes VisibilityTimeout=30,MessageRetentionPeriod=345600

📤
プロデューサー(送る側)

プロデューサーはメッセージをキューに送るアプリです。例えば Web サーバーが注文情報をキューに投入するケースが典型例です。SendMessage API でメッセージを送ったら、それで完了。コンシューマーの応答を待ちません(非同期通信)。送る側は受け取る側の状態を一切知らなくて OK です。

ポイント
  • SendMessage API でキューにメッセージを送る
  • メッセージは最大 256KB(それ以上は S3 + ポインタ方式)
  • 送信したら完了 — コンシューマーを待たない(非同期)

📬
キュー(メッセージを預かる場所)

キューはメッセージを一時的に保持するバッファです。送る側が毎秒1000件送っても、受け取る側が毎秒100件しか処理できなくても、キューが溜めて吸収してくれます。セール時のアクセス急増でも、キューがあればシステムが落ちずに済みます。

ポイント
  • メッセージ保持期間: デフォルト 4日、最大 14日
  • Standard キュー — ほぼ無制限のスループット、順序は保証されない
  • FIFO キュー — 順序保証 + 正確に1回の処理、秒間300件まで

📥
コンシューマー(受け取る側)

コンシューマーはキューからメッセージを取り出して処理するアプリです。SQS はプル型なので、コンシューマーが自分から「メッセージある?」と取りに行きます(キューから自動で届くわけではない)。処理が終わったら 自分でメッセージを削除する必要があります。削除しないとメッセージがキューに戻って二重処理されます。

ポイント
  • ReceiveMessage API でキューにメッセージを取りに行く(プル型)
  • 処理が終わったら DeleteMessage API で自分で消す
  • 消し忘れると可視性タイムアウト後にキューに戻る(二重処理の原因)

👻
可視性タイムアウトとは何か

可視性タイムアウト(Visibility Timeout)は、コンシューマーがメッセージを受信してから、他のコンシューマーに見えなくなる期間です。デフォルトは30秒で、0秒から最大12時間まで設定できます。この間にコンシューマーがメッセージを処理し、DeleteMessage を呼び出す必要があります。

可視性タイムアウトが切れる前に処理が完了しない場合、メッセージはキューに戻り、別のコンシューマーが再度受信できるようになります。これは「二重処理」のリスクを意味するため、コンシューマーの処理は冪等(べきとう)であるべきです。つまり、同じメッセージを2回処理しても結果が変わらないように設計します。

処理に予想以上の時間がかかる場合は、ChangeMessageVisibility API で可視性タイムアウトを延長できます。逆に、処理が非常に速い場合はタイムアウトを短く設定して、失敗時のリカバリを高速化できます。適切なタイムアウト値は「平均処理時間の2~3倍」が目安です。

受信可視性タイムアウト(30秒)DeleteタイムアウトDelete前にタイムアウトすると → メッセージがキューに復帰
処理成功パターン

タイムアウト内に処理完了 → DeleteMessage → メッセージが完全に削除される。これが正常フローです。

処理失敗パターン

タイムアウト切れ or 例外発生 → DeleteMessage が呼ばれない → メッセージがキューに復帰し、再処理される。receiveCount が増加する。

🗑️
メッセージの削除タイミング

SQS のメッセージは自動では削除されません。コンシューマーが処理成功後に DeleteMessage API を明示的に呼び出す必要があります。これは「処理が本当に完了したことをコンシューマー自身が保証する」というSQSの設計哲学です。

DeleteMessage には ReceiptHandle が必要です。これは ReceiveMessage のレスポンスに含まれる一時的なトークンで、「このメッセージを受信したのは自分だ」という証明です。同じメッセージでも受信するたびに異なる ReceiptHandle が発行されるため、古い ReceiptHandle では削除できません。

メッセージの保持期間(MessageRetentionPeriod)を過ぎると、DeleteMessage が呼ばれなくてもメッセージは自動的に削除されます。デフォルトは4日(345,600秒)、最大14日(1,209,600秒)です。DLQ に移動したメッセージも同じ保持期間が適用されるため、調査が遅れるとメッセージが失われる可能性があります。

## メッセージ削除のコード例
response = sqs.receive_message(QueueUrl=queue_url)
receipt_handle = response['Messages'][0]['ReceiptHandle']
# 処理実行...
sqs.delete_message(
QueueUrl=queue_url,
ReceiptHandle=receipt_handle
)

💀
Dead Letter Queue(DLQ)とは何か

Dead Letter Queue(DLQ)は、処理に繰り返し失敗したメッセージの退避先となるキューです。メインキューにリドライブポリシーを設定し、maxReceiveCount を指定します。メッセージの受信回数がこの値に達すると、自動的にDLQに移動されます。

DLQ の重要な制約は、メインキューと同じタイプである必要があることです。Standard キューの DLQ は Standard、FIFO キューの DLQ は FIFO でなければなりません。また、DLQ はメインキューと同じ AWS アカウント・リージョンに作成する必要があります。

DLQ に溜まったメッセージは、CloudWatch アラーム(ApproximateNumberOfMessagesVisible メトリクス)で監視し、速やかに原因調査を行います。原因を修正した後は、AWS コンソールまたは StartMessageMoveTask API でメッセージを元のキューにリドライブ(再送)できます。DLQ がないと、毒メッセージ(poison message)がメインキューを詰まらせ続ける問題が発生します。

メインキューmaxReceiveCount: 33回失敗Dead Letter Queue調査 → リドライブ元のキューに再送
DLQ の監視は必須: DLQ にメッセージが溜まっているということは、アプリケーションに問題がある証拠です。CloudWatch アラームを設定し、DLQ のメッセージ数が0を超えたら通知を送る設定にしましょう。

Long Polling vs Short Polling

Short Polling(WaitTimeSeconds=0)は、キューにメッセージがなくても即座に空のレスポンスを返します。さらに、SQS の内部サーバーのサブセットだけをサンプリングするため、メッセージが存在しても取得できない場合があります(false empty response)。ポーリング間隔を短くすると大量の空リクエストが発生し、コストが増大します。

Long Polling(WaitTimeSeconds=1~20)は、メッセージが到着するかタイムアウトするまで待機します。SQS の全サーバーをクエリするため、false empty response が発生しません。空リクエストが大幅に減少し、コスト削減とレイテンシ改善を同時に実現できます。

Long Polling は、キューの設定(ReceiveMessageWaitTimeSeconds 属性)またはリクエスト単位(WaitTimeSeconds パラメータ)で有効化できます。ほぼ全てのユースケースで Long Polling が推奨され、AWS のベストプラクティスでもあります。SAA 試験では「SQS のコストを削減するには?」という問題で Long Polling が正解になることが頻出します。

Short Polling(WaitTimeSeconds = 0)
ConsumerQueueある?→ない ×5回5回分の API 課金が発生
Long Polling(WaitTimeSeconds = 20)
ConsumerQueue来たら教えて(1回だけ)待機 → メッセージ来たら即返却(API 1回分)
比較項目Short PollingLong Polling
空レスポンス多い少ない
コスト高い低い
サーバークエリ一部のみ全サーバー
レイテンシ低い(即応答)低い(即配信)

📝
AWS 認定試験(SAA)レベルの問題

Q1.SQS キューのコンシューマーがメッセージを受信した後、処理に失敗しました。メッセージが他のコンシューマーに再度配信されるのはどのタイミングですか?
A.即座に他のコンシューマーに配信される
B.可視性タイムアウトが切れた後に配信される
C.メッセージの保持期限が切れた後に配信される
D.コンシューマーが明示的にメッセージを返却した後に配信される
Q2.SQS のコストを削減するために最も効果的な方法はどれですか?
A.キューの暗号化を無効にする
B.メッセージの保持期間を短くする
C.Long Polling を有効にし、バッチ操作を使用する
D.Standard キューから FIFO キューに変更する
Q3.アプリケーションが SQS キューからメッセージを処理していますが、同じメッセージが複数回処理されることがあります。この問題を解決するための最も適切なアプローチはどれですか?
A.可視性タイムアウトを24時間に設定する
B.コンシューマーの処理を冪等(べきとう)にする
C.キューの maxReceiveCount を 1 に設定する
D.Short Polling に変更する

関連コンテンツ