0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

SAMの`SQSPollerPolicy`が1行で肩代わりしている3つのIAM権限

0
Posted at

背景

SQS(メインキュー+DLQ)とLambdaによるメッセージキュー処理をAWS SAMで構築しました。VisibilityTimeoutの計算根拠と、DLQへの振り分け条件を実装ベースで整理します。

1. テンプレート全体(DLQ→メインキュー→Lambdaの順に定義する理由)

Resources:
  BatchDLQ:
    Type: AWS::SQS::Queue
    Properties:
      MessageRetentionPeriod: 86400

  BatchQueue:
    Type: AWS::SQS::Queue
    Properties:
      VisibilityTimeout: 180
      RedrivePolicy:
        deadLetterTargetArn: !GetAtt BatchDLQ.Arn
        maxReceiveCount: 3

  ProcessFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: src/
      Handler: app.lambda_handler
      Policies:
        - SQSPollerPolicy:
            QueueName: !GetAtt BatchQueue.QueueName
      Events:
        SQSEvent:
          Type: SQS
          Properties:
            Queue: !GetAtt BatchQueue.Arn
            BatchSize: 5

BatchQueueがRedrivePolicyでBatchDLQのARNを参照するため、CloudFormationの依存解決の都合上DLQを先に定義する必要があります。

2. VisibilityTimeoutはLambdaタイムアウトの6倍が目安

VisibilityTimeout: 180   # Lambdaタイムアウト(30秒) × 6

この計算式はAWS推奨値です。可視性タイムアウトがLambdaの処理時間より短いと、処理中に同じメッセージが再度キューに出現し、二重処理が発生します。「6倍」という余裕を持たせることで、リトライ処理や一時的な遅延にも耐えられるようにしています。

3. SQSPollerPolicyが付与する実際の権限

Policies:
  - SQSPollerPolicy:
      QueueName: !GetAtt BatchQueue.QueueName

この2行が実際に付与しているのは以下3つの権限です。

sqs:ReceiveMessage      # キューからメッセージを取り出す
sqs:DeleteMessage       # 処理完了後にメッセージを削除する
sqs:GetQueueAttributes  # キューの属性情報を取得する

コンソールで同じ権限を用意する場合、IAMロールにAWSLambdaSQSQueueExecutionRoleマネージドポリシーを手動アタッチすることになります。

4. DLQへの振り分けをコードでテストする

if body.strip().lower() == "error":
    raise ValueError(f"意図的なエラー: messageId={message_id}, body={body}")

このLambdaはerrorという本文を受信すると意図的に例外を投げます。SQSは失敗を検知するとVisibilityTimeout後に再度メッセージをキューに戻し、maxReceiveCount(今回は3回)失敗するとDLQに移動します。

1回目の失敗 → 180秒後に再試行
2回目の失敗 → 180秒後に再試行
3回目の失敗 → DLQへ移動

DLQに移動するまで最大180秒×3回≒9分かかるため、動作確認をすぐにしたい場合はVisibilityTimeoutを一時的に10秒程度に下げて試すと早く結果が見られます。

5. BatchSize: 5によるバッチ処理

for record in event["Records"]:
    message_id = record["messageId"]
    body = record["body"]

BatchSize: 5を指定すると、送信タイミングによっては最大5件のメッセージがまとめて1回のLambda呼び出しに渡されます。event["Records"]をループする実装にしておけば、1件でも複数件でも同じコードで処理できます。

まとめ

VisibilityTimeoutの計算根拠とSQSPollerPolicyが肩代わりする3つの権限、この2点がSAMのSQS連携で押さえておくべきポイントでした。DLQへの実際の振り分け確認手順は元記事にまとめています。

→ SQS + Lambdaでメッセージキュー処理を実装するハンズオン(ブログ)

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?