Amazon SQS 入門
Amazon Simple Queue Service(SQS)は、AWS が提供するフルマネージドのメッセージキューサービスです。 アプリケーション同士を疎結合にし、負荷の平準化や非同期処理の基盤として広く使われます。
この記事では、SQS を初めて触るときに押さえておきたい概念と、設計・運用でつまずきやすいポイントを整理します。
SQS でできること
Section titled “SQS でできること”SQS は「メッセージを一時的に預かり、別のコンポーネントが取り出す」ためのキューです。 送信側(プロデューサー)と受信側(コンシューマー)を直接つながずに処理を分離できます。
flowchart LR
P[プロデューサー] -->|SendMessage| Q[(SQS キュー)]
Q -->|ReceiveMessage| C1[コンシューマー A]
Q -->|ReceiveMessage| C2[コンシューマー B]
典型的な用途は次のとおりです。
| 用途 | 説明 |
|---|---|
| 非同期処理 | API が即座に応答し、重い処理をワーカーに任せる |
| 負荷の平準化 | スパイク時にメッセージをキューに溜め、処理能力に合わせて消化する |
| 疎結合 | 送信側・受信側のデプロイや障害を独立させる |
| リトライの分離 | 失敗した処理を DLQ に逃がし、本流を止めない |
| 用語 | 意味 |
|---|---|
| キュー(Queue) | メッセージを格納する論理的な入れ物 |
| メッセージ(Message) | 本文(最大 256 KiB)と属性・メタデータの組 |
| プロデューサー | SendMessage などでメッセージを送る側 |
| コンシューマー | ReceiveMessage で取り出し、処理後に DeleteMessage する側 |
| 可視性タイムアウト | 受信後に他コンシューマーから見えなくなる時間 |
| DLQ(Dead-Letter Queue) | 何度も処理に失敗したメッセージを退避するキュー |
Standard キューと FIFO キュー
Section titled “Standard キューと FIFO キュー”SQS には大きく Standard と FIFO の2種類があります。用途に応じて選びます。
| 項目 | Standard キュー | FIFO キュー |
|---|---|---|
| スループット | ほぼ無制限(高スループット向け) | 300 TPS(バッチ利用で拡張可能) |
| 配信順序 | ベストエフォート(順不同のことがある) | 送信順を保証 |
| 重複 | 少なくとも1回(重複の可能性あり) | 重複排除(同一メッセージの再送を抑制) |
| キュー名 | 任意 | 末尾が .fifo 必須 |
| 料金 | リクエスト課金 | Standard よりやや高め |
| 向いている例 | ログ集約、通知、汎用ジョブ | 注文処理、在庫引当など順序が重要な処理 |
選び方の目安
- 順序や重複が厳密でなく、スループットを優先する → Standard
- 「同じ注文を二重に処理してはいけない」「処理順を守りたい」 → FIFO
FIFO では MessageGroupId(同一グループ内で順序保証)と MessageDeduplicationId(重複排除)の指定が重要です。
メッセージのライフサイクル
Section titled “メッセージのライフサイクル”コンシューマーがメッセージを受け取ってから削除するまでの流れを理解しておくと、二重処理やメッセージ消失の原因を切り分けやすくなります。
sequenceDiagram
participant P as プロデューサー
participant Q as SQS
participant C as コンシューマー
P->>Q: SendMessage
Q->>C: ReceiveMessage
Note over Q,C: 可視性タイムアウト中は他から見えない
C->>C: ビジネス処理
alt 成功
C->>Q: DeleteMessage
else タイムアウト前に Delete しない
Q->>C: 再配信(別ワーカーにも届く可能性)
end
- 送信: プロデューサーがキューにメッセージを投入する
- 受信: コンシューマーが
ReceiveMessageで取得する(この時点ではキューからは消えない) - 処理中: 可視性タイムアウトの間、同じメッセージは他の受信者には見えない
- 削除: 処理が成功したら
DeleteMessage(ReceiptHandle必須)でキューから除去する - 再配信: 削除されずに可視性タイムアウトを過ぎると、再度配信対象になる
可視性タイムアウト
Section titled “可視性タイムアウト”デフォルトは 30 秒です。処理にかかる時間より十分長く設定し、処理中に同じメッセージが別ワーカーに渡らないようにします。
長い処理では ChangeMessageVisibility で延長できます。逆に、処理が明らかに失敗したときは 0 に戻して早く再試行させることもあります。
少なくとも1回配信(at-least-once)
Section titled “少なくとも1回配信(at-least-once)”SQS は 少なくとも1回 配信を保証します。つまり、同じメッセージが複数回届く可能性があります。 コンシューマー側は 冪等性(同じメッセージを何度処理しても結果が壊れない)を前提に実装するのが定石です。
ロングポーリングとショートポーリング
Section titled “ロングポーリングとショートポーリング”ReceiveMessage では WaitTimeSeconds で待ち方を制御します。
| 方式 | WaitTimeSeconds | 特徴 |
|---|---|---|
| ショートポーリング | 0 | 即座に返る。空キューだと無駄な API 呼び出しが増えやすい |
| ロングポーリング | 1〜20 | メッセージが来るまで待機。空ポーリングを減らしコスト・負荷を抑えられる |
新規キューでは ReceiveMessageWaitTimeSeconds(キュー属性)を 20 にしておく運用が一般的です。
Dead-Letter Queue(DLQ)
Section titled “Dead-Letter Queue(DLQ)”同じメッセージが何度も処理に失敗すると、本キューで無限に再配信が続きます。 DLQ に退避させ、本流のコンシューマーを守ります。
flowchart LR
M[メッセージ] --> Q[本キュー]
Q -->|処理失敗が閾値超え| DLQ[DLQ]
DLQ --> O[運用・調査・再投入]
設定の要点:
- 本キューに Redrive policy を設定し、DLQ の ARN を指定する
maxReceiveCount(何回受信したら DLQ に送るか)を決める(例: 3〜5)- DLQ のメッセージはアラート対象にし、原因調査後に手動またはスクリプトで再投入する
DLQ は「ゴミ箱」ではなく 障害の観測点 として扱うのがおすすめです。
代表的なアーキテクチャパターン
Section titled “代表的なアーキテクチャパターン”ワーカープール
Section titled “ワーカープール”複数の EC2 / Lambda / ECS タスクが同じキューをポーリングし、並列に処理します。 Standard キューでは複数ワーカーにメッセージが分散されます。
ファンアウト(SNS + SQS)
Section titled “ファンアウト(SNS + SQS)”1つのイベントを SNS トピックに publish し、複数の SQS キューに配信してサブシステムごとに処理させるパターンです。 通知・監査・非同期ジョブの分岐に向いています。
Lambda トリガー
Section titled “Lambda トリガー”SQS をイベントソースに Lambda を起動できます。
バッチサイズや ReportBatchItemFailures(部分失敗の報告)を使うと、失敗したメッセージだけ再試行できます。
設計・運用のベストプラクティス
Section titled “設計・運用のベストプラクティス”メッセージ本文の設計
Section titled “メッセージ本文の設計”- 本文に巨大なペイロードを載せず、S3 のオブジェクトキーや ID だけを送る(キューは軽く、実データは別ストア)
- スキーマのバージョンや
correlationIdを属性に載せ、トレースしやすくする
タイムアウトとリトライ
Section titled “タイムアウトとリトライ”- 可視性タイムアウト > 処理の p99 時間 を目安にする
- 指数バックオフはコンシューマー側の再試行設計とセットで考える(SQS 自体は再配信間隔を細かく制御しない)
セキュリティ
Section titled “セキュリティ”- キューポリシーと IAM で最小権限(
sqs:SendMessage/ReceiveMessage/DeleteMessageを役割ごとに分離) - 機密データは本文に平文で載せない。必要なら KMS で暗号化(SSE-SQS / SSE-KMS)
CloudWatch メトリクスで次を監視します。
| メトリクス | 見る意味 |
|---|---|
ApproximateNumberOfMessagesVisible | 滞留(バックログ)の増加 |
ApproximateAgeOfOldestMessage | 最古メッセージの待ち時間(SLA 違反の兆候) |
NumberOfMessagesDeleted | 正常消化の量 |
DLQ の ApproximateNumberOfMessagesVisible | 処理失敗の発生 |
よくある勘違い
Section titled “よくある勘違い”| 勘違い | 実際 |
|---|---|
| Receive したらメッセージは消える | DeleteMessage するまでキューに残る |
| SQS は exactly-once | 少なくとも1回。冪等性はアプリ側の責務 |
| DLQ に入ったら自動で復旧する | 人手または別ジョブで調査・再投入が必要 |
| FIFO なら Standard より常に正しい | FIFO はスループットと設定(GroupId など)の制約がある |
最小構成の例(AWS CLI)
Section titled “最小構成の例(AWS CLI)”キュー作成と送受信の流れです(リージョン・プロファイルは環境に合わせてください)。
# キュー作成aws sqs create-queue --queue-name my-app-jobs
# URL を取得(例)QUEUE_URL="https://sqs.ap-northeast-1.amazonaws.com/123456789012/my-app-jobs"
# 送信aws sqs send-message \ --queue-url "$QUEUE_URL" \ --message-body '{"jobId":"job-001","action":"resize-image"}'
# 受信(ロングポーリング 20 秒)aws sqs receive-message \ --queue-url "$QUEUE_URL" \ --wait-time-seconds 20 \ --visibility-timeout 60
# 処理成功後、ReceiptHandle を使って削除aws sqs delete-message \ --queue-url "$QUEUE_URL" \ --receipt-handle "<ReceiptHandle from receive-message>"本番では AWS SDK(例: AWS SDK for JavaScript v3 の @aws-sdk/client-sqs)や IaC(CloudFormation / Terraform / CDK)でキューと DLQ、IAM、監視アラームをまとめて定義するのが一般的です。
- SQS は 疎結合・非同期・負荷平準化 のためのマネージドキュー
- Standard は高スループット、FIFO は順序と重複排除が必要なとき
- 受信後は DeleteMessage までが1サイクル。処理時間と 可視性タイムアウト の整合が重要
- 少なくとも1回 配信を前提に 冪等 に実装する
- 失敗の観測と本流保護のために DLQ とメトリクス監視をセットで用意する
関連サービスとして、イベント配信には Amazon SNS、スケジュール実行には EventBridge、大規模ストリーミングには Kinesis なども選択肢になります。要件(順序、スループット、保持期間、再実行モデル)に応じて使い分けてください。