背景
SQS(メインキュー+DLQ)とLambdaによるメッセージキュー処理を、SAMを使わずコンソールで手動構築しました。ARNの手動配線とIAM権限の実体が見えてきます。
1. DLQを先に作ってARNを控えておく必要がある
メインキュー作成時にDLQのARNが必要なため、DLQを先に作成します。SAMなら!GetAtt BatchDLQ.Arnで自動参照できますが、コンソールでは作成後にARNをコピーして次のステップで貼り付けます。
① DLQ(BatchDLQ)作成 → ARNを控える
② メインキュー(BatchQueue)作成時にそのARNを貼り付け
2. 可視性タイムアウトはLambdaタイムアウトの6倍が目安
Lambda関数のタイムアウト(30秒)× 6 = 可視性タイムアウト 180秒
AWS推奨のこの計算式には理由があります。処理中に可視性タイムアウトが切れると、同じメッセージが再度キューに出現し、二重処理が発生してしまいます。SAMではVisibilityTimeout: 180の1行ですが、コンソールでは自分で計算して入力する必要があります。
3. DLQへの振り分けはmaxReceiveCountで制御
1回目の失敗 → 可視性タイムアウト後に再試行
2回目の失敗 → 再試行
3回目の失敗 → DLQへ移動(maxReceiveCount: 3)
DLQ設定は「デッドレターキューを有効にする」→ DLQのARNを貼り付け → 最大受信数を入力、という3ステップです。
4. SQSポーリング権限はIAMコンソールで手動アタッチ
デフォルトのLambda実行ロールはCloudWatch Logsへの書き込み権限しか持っていません。SQSからメッセージを取り出す権限は別途アタッチが必要です。
Lambda実行ロールの画面 → 「ポリシーをアタッチ」→ AWSLambdaSQSQueueExecutionRole を検索してチェック
このマネージドポリシーには以下3つの権限が含まれています。
-
sqs:ReceiveMessage— キューからメッセージを取り出す -
sqs:DeleteMessage— 処理完了後にメッセージを削除する -
sqs:GetQueueAttributes— キューの属性情報を取得する
SAMではSQSPollerPolicy: QueueName: !GetAtt BatchQueue.QueueNameの2行がこの3権限をまとめて付与しています。
5. DLQへの実際の移動には数分かかる
テスト用にerrorというメッセージを送ると、Lambdaが例外を投げてDLQに移動する動きを確認できます。ただし可視性タイムアウト(180秒)× 3回失敗を待つ必要があるため、最大9分程度かかります。すぐに確認したい場合は、検証用にキューの可視性タイムアウトを一時的に10秒に短縮すると早く結果が見られます。
if body.strip().lower() == "error":
raise ValueError(f"意図的なエラー: messageId={message_id}, body={body}")
6. SAMとの対比
| SAMの記述 | コンソールでの実体 |
|---|---|
RedrivePolicy: maxReceiveCount: 3 |
メインキューのDLQ設定で最大受信数を入力 |
VisibilityTimeout: 180 |
可視性タイムアウトを手動入力(Lambdaタイムアウト×6が目安) |
SQSPollerPolicy(自動) |
IAMコンソールでAWSLambdaSQSQueueExecutionRoleを手動アタッチ |
sam delete |
トリガー・Lambda・SQS×2・IAMロールを個別に削除 |
まとめ
可視性タイムアウトの計算根拠とDLQへの振り分け条件、IAM権限の中身、この3点がSAMでは隠れている部分でした。動作テストの詳細手順はこちらにまとめています。