SQSで正常に処理できないメッセージをデッドレターキューに移動してSNSで通知する
全体図
3回に分けてSQSを使用した疎結合なシステムを構築していきます。
今回はその3回目となります。

前回は下記を参照ください。
今回のゴール
SQSキューのメッセージをある一定回数正しく処理できない時、デッドレターキューに移動して、SNSで通知するように設定します。
(上記図中の赤枠の部分)

処理できなかったメッセージをデッドレターキューに移動して、なぜエラーになったかの原因究明するような運用になるかと思います。
デッドレターキューを作成
デッドレター用のキューを作成します。
キューのタイプは元のキューと同じにしないといけないので、FIFOとしました。
[タイプ]:FIFO
[名前]:DLQ-test-queue.fifo
[メッセージ保持期間]:8日 デッドレターキューでの保持期間ではなく、通常のキューに入ってからの期間を設定しますので、通常のキュー設定より長く設定します。
[コンテンツに基づく重複削除]の項目に関しては、どちらの設定にしてもMessageDeduplicationIdにはmessageIdがセットされるようでした。

今回はメッセージを暗号化したいので、暗号化を有効にして、CMKを指定しました。

通常のキューの設定
通常のキューに先ほど作成したデッドレターキューの設定をします。
通常のキューの「編集」ボタンをクリックして、デッドレターキュー欄で有効を選択して、作成済のデッドレターキューを選択します。
最大受信数はデフォルトの10のままとしました。

デッドレターキューの確認
Lambda関数で例外が発生するようにコードを変更して、メッセージを送信します。
CloudWatchで確認すると、エラーが10回発生した後にデッドレターキューにメッセージが移動しました。

SNS通知の設定
次に、デッドレターキューにメッセージが入った時にSNS通知するように設定します。
デッドレターキューのモニタリングタブを見てみると、先ほどデッドレターキューに移動したメッセージが ApproximateNumberOfMessagesVisibleメトリクスにカウントされていました。
このSQS ApproximateNumberOfMessagesVisibleを使用していきます。

SNSの作成
SNSトピックを作成します。
[タイプ]:スタンダード
[名前]:topic-sqs-deadletter
[表示名]: sqs-deadletter

続いてサブスクリプションを登録します。
[トピックARN]:先ほど作成したトピックを選択
[プロトコル]:Eメール
[エンドポイント]:メールアドレスを入力

登録後、確認メールが届きますので、リンクをクリックして承認します。
CloudWatchEventのアラームの作成
SQSのデッドレターキュー(DLQ-test-queue.fifo)のApproximateNumberOfMessagesVisibleを選択します。

“5分間”で”平均””0より大きい時”を条件としました。

先ほど作成したSNSトピック(topic-sqs-deadletter)を選択しました。

[アラーム名]:alarm_sqs_deadletter_NG

確認
一旦デッドレターキューをクリアして、アラームが正常な状態から、デッドレターキューにメッセージを入れます。
暫くするとアラーム状態となり、メールが送信されていることが確認できました。
補足
通常のキューに入ったメッセージとデッドレターキューに入ったメッセージの違いを比べてみました。
【値が同じ項目 ※ 主要な項目のみ抜粋】
- messageId
- body
- MessageGroupId
- messageAttributes
【値が違う項目 ※ 主要な項目のみ抜粋 】
- SequenceNumber
- MessageDeduplicationId messageIdがセットされる
※デッドレターキューに入ったメッセージのMessageDeduplicationIdの値にmessageIdがセットされるところは注意が必要かもしれません。
