【これで理解できる】SQSのデッドレターキューを理解したかったのでSQS+Lambdaのリトライ処理を実装してみた

AWS

はじめに

最近、仕事でSQSを使う機会があったのですが、デッドレターキューやSQSによるリトライ処理がイマイチ理解できていませんでした。
AWSの公式ドキュメントやブログ記事などを見てもあまり理解できなかったため、実際にサンプルアプリを作って検証しました。

実施内容(概要)

実施内容は以下です。

  • LambdaにSQSでメッセージを送信する
  • Lambdaはエラーとなるような処理とする
  • 複数リトライ後、SQSのメッセージがデッドレターキューに入ることを確認する
  • デッドレターキューに入ったメッセージを使って再処理できることを確認する

実施内容(詳細 – 設定)

IAM

一般的なユースケースからLambdaを選択し、次のステップ:アクセス権限を押します。

ポリシーとしてAmazonSQSFullAccessCloudWatchLogsFullAccessを選択します。理由はそれぞれ以下です。選択後、次のステップ:タグを押します。

  • AmazonSQSFullAccess:LambdaがSQSメッセージを処理するため
  • CloudWatchLogsFullAccess: LambdaがSQSメッセージ処理後にCouldWatch logsにログを出力するため

タグの設定はスキップし、次のステップ:確認を押します。

一通りの内容を確認します。また、ロール名は適当に付けてロールの作成を押します。

これでIAMの設定は完了です。

Lambda

次にLambdaで検証用の関数を作成します。

サンプルアプリの言語としてPythonを選択します。

アクセス権限は既存のロールを選択し、先ほど作成したロールを選択します。

コードは以下のコードを貼り付けて、必ずエラーとなるようにします。

import json

def lambda_handler(event, context):
    msg = event['Records'][0]['body']
    print(msg)
    try:
        a = 1 / 0 
    except:
        raise Exception('ERROR!!')
    return {
        'statusCode': 200,
        'body': json.dumps('Hello from Lambda!')
    }

以下でSQSの設定後に、トリガーを追加をクリックし、以下設定します。

  • トリガーとしてSQSを選択
  • SQSキュー:sample-message-queue
  • バッチサイズ:1
  • バッチウィンドウ:0

SQS

今回は以下2つのキューを作成します。

  • sample-message-queue:上記Lambdaにメッセージを送信するキュー
  • sample-message-queue-dlq:デッドレターキューを格納するキュー

それぞれ以下のように作成していきます。

デッドレターキューを格納するキュー

  • タイプ:標準
  • 名前:sample-message-queue-dlq
  • 設定:デフォルト
  • アクセスポリシー:デフォルト

Lambdaにメッセージを送信するキュー

  • タイプ:標準
  • 名前:sample-message-queue
  • 設定:デフォルト
  • アクセスポリシー:デフォルト
  • デッドレターキュー:有効
  • キューの選択:sample-message-queue-dlq
  • 最大受信数:5:sample-message-queueが5回リトライ後、メッセージがsample-message-queue-dlq移動する

実施内容(詳細 – 検証)

検証1:リトライ後、SQSのメッセージがデッドレターキューに入ることを確認する

以下の手順でSQSでメッセージを送信してみます

  • SQSでsample-message-queueを選択し、メッセージを送受信をクリック
  • メッセージ本文にtestと入力する
  • 配信遅延時間:デフォルト(=0秒)とする
  • メッセージを送信

すると、以下のようにsample-message-queueで処理中のメッセージが1つあることがわかります。

sqs process message

数分後に、CloudWatchログを確認すると、最大受信数分だけLambdaがリトライ処理をしていることがわかります。

SQSをみると、sample-message-queue-dlqにメッセージが移動していることがわかります。

次に、以下手順により、先ほど送ったメッセージを取得できていることを確認できます。

  • sample-message-queue-dlqを開き、メッセージを送受信を押す
  • メッセージをポーリングを押す
  • 先ほど送ったメッセージを取得し、testと書かれたメッセージを確認できる

スクリーンショットを取得し忘れましたが、、上記手順で確認できるはずです。

検証2:デッドレターキューに入ったメッセージを使って再処理できることを確認する

検証1でデッドレターキューにメッセージが入り、中身を確認することができました。

次に、このメッセージを再度処理してみましょう。

以下手順でメッセージを再処理できます。

  • sample-message-queue-dlqを開き、DLQ再処理の開始を押す
  • メッセージの送信先:再処理のためにカスタム送信先に移動を押す
  • 既存のキュー:sample-message-queueを押す
  • DLQ再処理を押す

上記により、先ほどsample-message-queue-dlqに入っていたメッセージが、sample-message-queueに移動していることがわかります。

再度CloudWatch logsをみると、最大受信数分だけLambdaがリトライ処理をしていることがわかります。

まとめ

今回はSQSのデッドレターキューを理解するために、SQS+Lambdaによりリトライ処理を実装してみました。
自分で手を動かして実装したことで、SQSについて理解が深まりました。
今後もAWSの他サービスやプログラミングに関する検証系のブログ記事を書いていこうと思います。

参考

SQS → Lambdaのリトライ処理について整理してみた - Qiita
2018年の6月より、AWS LambdaのイベントソースとしてSQSが選択できるようになりました。 今回はLambdaのイベントソースでSQSを選択し、Lambda側で処理が失敗した場合、どのようにリトライ処理が行われるのかについ...
タイトルとURLをコピーしました