[アップデート] Amazon SQS の DLQ(デッドレターキュー)の再処理を AWS SDK/CLI を使って処理出来るようになりました

2023.06.11

いわさです。

SQS で正常にメッセージが処理されなかった場合に未処理のメッセージを DLQ(デッドレターキュー)に移動することが出来ます。
デッドレターキュー上で処理されなかったメッセージを確認して、アプリケーションの問題の特定に役立てることが出来ます。

従来はその後アプリケーションが復旧したら、マネジメントコンソール上から DLQ の再処理機能を使って元のキュー(あるいは別のキュー)へメッセージを戻して処理を再開することが出来ました。

これまではこの DLQ の再処理はマネジメントコンソールでのみサポートされていましたが、先日のアップデートで AWS SDK や AWS CLI からも操作が出来るようになりました。

DLQ の再処理部分を AWS SDK や AWS CLI から操作出来るようになったというだけといえばだけなので、既存のアプリケーションに影響は発生しません。
また、マネジメントコンソールが操作する場合でも将来的に CloudTrail に記録される内容が変わるようです。

マネジメントコンソールからの DLQ の再処理

メッセージの処理に失敗するキューを用意してみます。
SQS から Lambda へは同期実行されるので、次のようにエラーが発生する Lambda 関数をトリガーさせるだけで良いです。

lambda_function.py

import json

def lambda_handler(event, context):
    raise Exception('hoge-lambda-error')

そして、このキューに DLQ として用意した別のキューを設定します。

この状態でメッセージを送信すると Lambda 関数が失敗し処理出来なかったメッセージが DLQ へ送信されます。
従来は DLQ に送信されたことを検知するために次のような方法で CloudWatch メトリクスなどでApproximateNumberOfMessagesVisibleを監視して通知することが多かったと思います。

そして、通知受信後にマネジメントコンソールからメッセージ詳細を確認し、トラブルシューティング完了後に未処理のメッセージを個別に削除するか、あるいは DLQ から元のキューや別のキューへメッセージを転送していたと思います。

AWS CLI から実行してみる

上記のマネジメントコンソールからの DLQ 再処理の際には、内部的には CreateMoveTask API が実行されていますが、この API はユーザー側へ利用が許可されているものではありませんでした。
このあたりの自動化が必要な場合は公式ドキュメントの記述のあるようにSendMessageBatchReceiveMessageDeleteMessageBatchなどを使う方法がありましたが、マネジメントコンソールの一括再処理と同様の操作が API で実行出来るようになりました。

今回新たに以下の 3 つの API が追加され、ここから DLQ 再処理タスクの操作が AWS SDK や CLI から可能になっています。

先程のマネジメントコンソールと同様に別のキューへ DLQ のメッセージを移動させる場合は次のコマンドを実行してみました。

% cat start-message-move-task.json
{
    "SourceArn": "arn:aws:sqs:ap-northeast-1:123456789012:hoge0611dlq",
    "DestinationArn": "arn:aws:sqs:ap-northeast-1:123456789012:hoge0611-2"
}
% aws-v1 sqs start-message-move-task --cli-input-json file://start-message-move-task.json  
{
    "TaskHandle": "hogehoge"
}

DLQ に転送されていたメッセージが別のキューへ移動されました。

FIFO では従来同様サポートされていない

SQS の DLQ ですが、ベースのキューと DLQ のタイプは同じものである必要があります。
そのため FIFO キューの DLQ も FIFO である必要があります。

そして、従来のマネジメントコンソールからの DLQ 再処理ですが、FIFO キューについてはサポートされていませんでした。

今回追加された API でも従来と同様に FIFO キューについては残念ながらサポートされていませんのでご注意ください。
確認してみたところ次のようにエラーが発生しました。

% aws-v1 sqs start-message-move-task --cli-input-json file://start-message-move-task.json

An error occurred (AWS.SimpleQueueService.UnsupportedOperation) when calling the StartMessageMoveTask operation: FifoQueue(SourceArn) in StartMessageMoveTask operation are not supported.

マネジメントコンソールからの操作 API も今回のものに統一されるっぽい

今回アップデート内容を確認していく中でドキュメントに次の記載がありました。

On August 31, 2023, the CloudTrail event names for dead-letter queue redrive will change on the Amazon SQS console. If you've set alarms for these CloudTrail events, you must update them now. The following are the new CloudTrail event names for DLQ redrive:

どうやら 2023 年 8 月 31 日以降は、マネジメント CloudTrail に記録されるイベント名が今回のものに変更されるとのことです。

本日時点ではマネジメントコンソールから DLQ 再処理でメッセージ移動を行った際は次のようにCreateMoveTaskが記録されていました。

{
    "eventVersion": "1.08",
:
    "eventSource": "sqs.amazonaws.com",
    "eventName": "CreateMoveTask",
    "awsRegion": "ap-northeast-1",
    "sourceIPAddress": "14.9.148.128",
    "userAgent": "AWS Internal",
    "requestParameters": {
        "taskName": "a35e141c-fbac-4adf-ab1a-9e9775ed4a45",
        "sourceArn": "arn:aws:sqs:ap-northeast-1:123456789012:hoge0611dlq",
        "destinationArn": "arn:aws:sqs:ap-northeast-1:123456789012:hoge0611-2"
    },
    "responseElements": {
        "status": "RUNNING",
        "approximateNumberOfMessagesMoved": 0,
        "createTime": 1686481865726,
        "taskHandle": "hogehogehogehoge==",
        "taskName": "a35e141c-fbac-4adf-ab1a-9e9775ed4a45",
        "sourceArn": "arn:aws:sqs:ap-northeast-1:123456789012:hoge0611dlq",
        "destinationArn": "arn:aws:sqs:ap-northeast-1:123456789012:hoge0611-2"
    },
    "requestID": "cc6da3c7-a8d9-50a7-b018-ff3806d0a712",
    "eventID": "10ea3c8d-03c3-4988-9549-d695e7ad3580",
    "readOnly": false,
    "eventType": "AwsApiCall",
    "managementEvent": true,
    "recipientAccountId": "123456789012",
    "eventCategory": "Management",
    "sessionCredentialFromConsole": "true"
}

8 月 31 日以降はStartMessageMoveTaskイベントとなるようです。
先程 CLI から使ったコマンドがStartMessageMoveTaskなのでマネジメントコンソールで内部的に使用される API が置き換わるようなイメージでしょうか。

{
    "eventVersion": "1.08",
:
    "eventSource": "sqs.amazonaws.com",
    "eventName": "StartMessageMoveTask",
    "awsRegion": "ap-northeast-1",
    "sourceIPAddress": "14.9.148.128",
    "userAgent": "aws-cli/1.27.151 Python/3.9.8 Darwin/22.5.0 botocore/1.29.151",
    "requestParameters": {
        "sourceArn": "arn:aws:sqs:ap-northeast-1:123456789012:hoge0611dlq",
        "destinationArn": "arn:aws:sqs:ap-northeast-1:123456789012:hoge0611-2"
    },
    "responseElements": {
        "taskHandle": "hogehogehoge=="
    },
    "requestID": "81dd47ee-b1e4-59e1-b800-1b1102d0866f",
    "eventID": "cbb27c38-edbb-4ef3-b2d0-eb4642b3792a",
    "readOnly": false,
    "eventType": "AwsApiCall",
    "managementEvent": true,
    "recipientAccountId": "123456789012",
    "eventCategory": "Management",
    "tlsDetails": {
        "tlsVersion": "TLSv1.2",
        "cipherSuite": "ECDHE-RSA-AES128-GCM-SHA256",
        "clientProvidedHostHeader": "ap-northeast-1.queue.amazonaws.com"
    }
}

もしCreateMoveTaskアクションで何らかのイベントやアラームを設定している場合はご注意ください。

さいごに

本日は Amazon SQS の DLQ(デッドレターキュー)の再処理を AWS SDK/CLI を使って処理出来るようになったので紹介しました。

マネジメントコンソール以外から DLQ のメッセージを処理する場合は複数のコマンドを組み合わせたカスタムコードが必要だったと思いますが、今回新たな API が利用出来るようになったことで簡単に API から利用出来るようになりました。

CreateMoveTaskのイベントを拾うケースあまり考えつかないですが、あるタイミングで変わるということなので注意したいというか、覚えておきたいですね。