目次
- キュータイプの選択
- 冪等性(最重要)
- 可視性タイムアウト
- デッドレターキュー(DLQ)
- メッセージの受信(ポーリング)
- 送信・バッチ処理
- Lambda との連携(イベントソースマッピング)
- 遅延・保持期間
- セキュリティ
- 監視・アラーム
- アーキテクチャパターン
- コスト最適化
- 運用チェックリスト
1. キュータイプの選択
| 観点 | Standard キュー | FIFO キュー |
|---|---|---|
| 配信保証 | 少なくとも1回(重複あり得る) | 正確に1回処理(重複排除ウィンドウ5分) |
| 順序 | ベストエフォート | メッセージグループ単位で厳密 |
| スループット | ほぼ無制限 | 高スループットモードで大幅に向上(リージョン依存) |
| 主な用途 | 大量の非同期処理、疎結合化 | 順序が重要な処理(決済、在庫更新など) |
- 基本は Standard を選び、順序・重複排除が本当に必要な場合のみ FIFO を選ぶ。
- FIFO を使う場合は
MessageGroupIdを細かく分割して並列度を確保する(単一グループだと実質シリアル処理になる)。 - 高スループットが必要な FIFO は「高スループットモード」(
DeduplicationScope=messageGroup、FifoThroughputLimit=perMessageGroupId)を有効化する。 - マルチテナントの Standard キューで特定テナントが他を圧迫する(noisy neighbor)場合は フェアキュー(
MessageGroupIdをテナントIDとして付与)を検討する。
2. 冪等性(最重要)
- Standard キューは 同一メッセージが複数回届く前提 で設計する。FIFO でも、可視性タイムアウト切れ等による再処理は起こり得る。
- コンシューマーは冪等に実装する。
- メッセージに一意のID(業務キー)を持たせ、DynamoDB の条件付き書き込み等で処理済みを記録する。
- 「処理済みチェック → 処理 → 記録」はアトミックに、もしくは処理自体を冪等(UPSERT など)にする。
- SQS の
MessageIdは再送時に変わるケースがあるため、業務側で生成した冪等キー を使う。
3. 可視性タイムアウト
- 処理時間の最大値より十分長く設定する(目安: 想定処理時間の数倍)。短すぎると処理中に他のコンシューマーが同じメッセージを受信してしまう。
- 処理時間が読めない場合は、処理中に
ChangeMessageVisibilityでハートビート的に延長する。 - Lambda をトリガーにする場合は、可視性タイムアウト ≥ Lambda タイムアウト × 6 が推奨値。
- 処理に失敗した際、即時リトライさせたいなら可視性タイムアウトを 0 に変更して戻すことも可能。
4. デッドレターキュー(DLQ)
- すべての本番キューに DLQ を設定する。毒メッセージ(何度処理しても失敗するメッセージ)が無限にリトライされるのを防ぐ。
maxReceiveCountは一時的な障害を吸収できる程度(例: 3〜5)に設定する。- DLQ のメッセージ保持期間は 元キューより長く 設定する(Standard キューではエンキュー時刻が引き継がれるため、短いと DLQ 到着直後に消える)。
- DLQ のメッセージ数(
ApproximateNumberOfMessagesVisible)に CloudWatch アラーム を設定する。 - 原因修正後は DLQ redrive(コンソール/API)で元キューへ戻す運用手順を用意しておく。
- FIFO キューの DLQ は FIFO である必要がある。
5. メッセージの受信(ポーリング)
- ロングポーリングを使う(
WaitTimeSecondsを最大 20 秒、またはキュー属性ReceiveMessageWaitTimeSeconds=20)。空レスポンスが減り、コストとレイテンシの両方が改善する。 MaxNumberOfMessages=10で一度に複数件受信する。- 処理が成功したメッセージだけを確実に
DeleteMessage(またはバッチ削除)する。削除漏れは重複処理の原因になる。 - コンシューマーの並列数はキューの滞留状況に応じてスケールさせる(後述の監視メトリクスを利用)。
6. 送信・バッチ処理
SendMessageBatch/DeleteMessageBatch/ChangeMessageVisibilityBatchで 最大10件をまとめる。API 呼び出し回数=コストが減る。- バッチ API は 部分失敗 があり得るため、レスポンスの
Failedを確認して再送する。 - SDK のリトライ設定(指数バックオフ + ジッター)を適切に構成する。
- 大きなペイロード(上限超過、または大きなデータ)は S3 に置き、SQS には参照だけを送る(Extended Client Library: Java / Python 等)。小さなメッセージに保つほどスループット・コスト面で有利。
7. Lambda との連携(イベントソースマッピング)
- 部分バッチレスポンス(
ReportBatchItemFailures)を有効にし、失敗したメッセージだけを再試行させる。これがないと1件の失敗でバッチ全体が再処理される。 BatchSizeとMaximumBatchingWindowInSecondsを調整して、呼び出し回数とレイテンシのバランスをとる。- 下流(DB・外部API)を保護するため 最大同時実行数(
MaximumConcurrency) を設定する。予約同時実行数で絞るとスロットリング→リトライ→DLQ 行きが起きやすいので、こちらを優先する。 - スパイクに即応したい・低レイテンシが必要な場合は、ESM の プロビジョンドモード を検討する。
- 可視性タイムアウトは前述の通り Lambda タイムアウトの6倍以上にする。
8. 遅延・保持期間
- メッセージ保持期間(デフォルト4日、最大14日)は、障害からの復旧にかかる時間を考慮して設定する。
- 特定時間後に処理させたい場合は遅延キュー(キュー単位)またはメッセージタイマー(メッセージ単位、Standard のみ)を使う。上限は15分なので、それ以上は EventBridge Scheduler 等を使う。
9. セキュリティ
- サーバー側暗号化: 新規キューは SSE-SQS がデフォルト有効。キーの管理・監査要件がある場合は SSE-KMS(カスタマー管理キー)を使い、KMS のデータキー再利用期間を調整して KMS 呼び出しコストを抑える。
- 最小権限: IAM ポリシー・キューポリシーで送信側には
sqs:SendMessage、受信側にはsqs:ReceiveMessage/sqs:DeleteMessage等、必要なアクションだけを許可する。 - キューポリシーで SNS/EventBridge 等から許可する場合は
aws:SourceArn/aws:SourceAccount条件で送信元を限定する(混乱した代理問題対策)。 - 転送時の暗号化:
aws:SecureTransport条件で HTTPS 以外を拒否する。 - VPC 内からのアクセスは VPC エンドポイント(PrivateLink) を使い、エンドポイントポリシーで対象キューを限定する。
- メッセージ本文に機密情報(個人情報・認証情報)をそのまま入れない。必要なら参照IDのみ渡す。
10. 監視・アラーム
主要な CloudWatch メトリクスとアラーム例:
| メトリクス | 見るポイント |
|---|---|
ApproximateAgeOfOldestMessage | 処理遅延の最重要指標。SLA を超えたらアラーム |
ApproximateNumberOfMessagesVisible | 滞留量。コンシューマーのスケール判断に使う |
ApproximateNumberOfMessagesNotVisible | 処理中(インフライト)件数。上限(Standard 約12万、FIFO 2万)に注意 |
NumberOfMessagesSent / NumberOfMessagesDeleted | 流入・処理量のバランス |
NumberOfEmptyReceives | 多ければロングポーリング未設定や過剰なコンシューマーを疑う |
DLQ の ApproximateNumberOfMessagesVisible | 1件以上でアラーム |
- EC2/ECS のコンシューマーは「1インスタンスあたりのバックログ」(滞留数 ÷ 稼働タスク数)を指標にターゲット追跡スケーリングする。
- 分散トレーシングが必要なら AWS X-Ray のトレースヘッダーを伝播させる。
11. アーキテクチャパターン
- ファンアウト: SNS トピック(または EventBridge)→ 複数 SQS キュー。各サブスクライバーが独立して処理・リトライできる。
- 負荷平準化(バッファ): スパイクを SQS で吸収し、下流は一定のペースで処理する。
- 優先度: SQS にはメッセージ単位の優先度がないため、優先度別にキューを分けてコンシューマーで高優先から読む。
- リクエスト/レスポンス: 一時キュー(Temporary Queue Client)や相関IDを用いる。ただし同期的な用途なら SQS 以外の手段も検討する。
- EventBridge Pipes を使うと、SQS → フィルタ/変換 → ターゲット をコードなしで構成できる。
12. コスト最適化
- ロングポーリング、バッチ API で リクエスト数を減らす(課金はリクエスト単位、64KB チャンクごとに1リクエスト換算)。
- 不要な
ReceiveMessageを空打ちしない(コンシューマーの過剰プロビジョニングを避ける)。 - SSE-KMS 利用時はデータキー再利用期間を長め(例: 最大24時間まで)にして KMS API コストを抑える。
- FIFO は Standard より単価が高いため、必要な場合のみ使う。
13. 運用チェックリスト
- Standard / FIFO の選定理由が明確
- コンシューマーが冪等
- 可視性タイムアウトが最大処理時間より十分長い(Lambda なら6倍以上)
- DLQ を設定し、保持期間を元キューより長くしている
- DLQ・メッセージ滞留時間にアラームがある
- DLQ redrive の手順がある
- ロングポーリング(20秒)を設定
- バッチ API を使用し、部分失敗を処理している
- Lambda では
ReportBatchItemFailuresと最大同時実行数を設定 - 暗号化(SSE)と最小権限ポリシー、HTTPS 強制
- ペイロードが大きい場合は S3 参照パターン
- 保持期間が障害復旧時間をカバーしている