DLQについて試してみた

# 背景・目的
DLQについて、まともに触ったことがなかったので
基本的な知識の整理と、ハンズオンで動かし感覚を養いたいと思います。

# まとめ
下記に特徴を整理します。

|特徴|説明|
|:--|:--|
|デッドレターキュー|・エラーのためにSWが処理できないメッセージを一時的に保存する特別なタイプのメッセージキュー<BR>・宛先が指定されていない。または目的の受信者が処理できないエラーを含むメッセージを格納する|
|デッドレターキューの重要性|誤ったメッセージや失敗したメッセージの一時的な保存場所として機能し、DLQはソースキューが未処理のメッセージであふれるのを防ぐ|
|デッドレターキューの利点|・通信コストの削減<BR>・トラブルシューティングの改善|
|デッドレターキューはどのような場合に使用すべきか|順序付けされていないキューの場合、アプリケーションが順序に依存しない場合、DLQを活用できる<BR><BR>FIFO キューの場合、すべてのメッセージは、次のメッセージを配信する前に処理する必要がある。FIFO キューではデッドレターキューを使用できるが、DLQ の実装も FIFO にする必要がある|
|デッドレターキューの仕組み|リドライブポリシーの作成しソフトウェアは、リドライブポリシーを参照してメッセージをデッドレターキューに移動する|
|リドライブポリシー|ソフトウェアがメッセージをデッドレターキューに移動するタイミングを決定するルールで構成される|


# 概要
下記を基に整理します。

https://aws.amazon.com/jp/what-is/dead-letter-queue/

## デッドレターキュとは
> デッドレターキュー (DLQ) は、エラーのためにソフトウェアシステムが処理できないメッセージを一時的に保存する特別なタイプのメッセージキューです。メッセージキューは、分散システムにおける非同期通信をサポートするソフトウェアコンポーネントです。これにより、ソフトウェアサービス間でメッセージを任意の量で送信でき、メッセージの受信者が常に待機している必要がなくなります。デッドレターキューは特に、宛先が指定されていない、または目的の受信者が処理できない、エラーを含むメッセージを格納します。

- エラーのためにSWが処理できないメッセージを一時的に保存する特別なタイプのメッセージキュー
- 宛先が指定されていない。または目的の受信者が処理できないエラーを含むメッセージを格納する

## デッドレターキューはなぜ重要か
デッドレターキュー (DLQ) は通常のメッセージキューと並んで存在します。誤ったメッセージや失敗したメッセージの一時的な保存場所として機能します。DLQ は、ソースキューが未処理のメッセージであふれるのを防ぎます。
> 例えば、通常のメッセージキューと DLQ を備えたソフトウェアを考えてみましょう。ソフトウェアは通常のキューを使用して、宛先に送信する予定のメッセージを保持します。受信者が送信メッセージへの応答またはその処理に失敗した場合、ソフトウェアはそのメッセージをデッドレターキューに移動します。

- DLQは通常のメッセージキューと同列
- 誤ったメッセージや失敗したメッセージの一時的な保存場所として機能する
- DLQはソースキューが未処理のメッセージであふれるのを防ぐ
- 例）通常のメッセージキュー＋DLQを備えたソフトウェア
    - ソフトウェアは通常のキューを使用して、宛先に送信する予定のメッセージを保持
    - 受信者が送信メッセージへの応答またはその処理に失敗した場合、ソフトウェアはそのメッセージをデッドレターキューに移動する

> メッセージが DLQ パイプラインに移動する場合、メッセージの内容の誤りと、受信者のシステムの変更の 2 つの原因が考えられます。

> 誤ったメッセージの内容
送信されたメッセージに誤りがある場合、メッセージは DLQ に移動します。ハードウェア、ソフトウェア、ネットワークの状態により、送信データが破損する可能性があります。例えば、ハードウェアの干渉により、送信中に情報の一部がわずかに変化します。予期しないデータ破損により、受信者はメッセージを拒否または無視する可能性があります。

> 受信者のシステムの変更
また、受信側のソフトウェアで送信者が気付いていない変更が行われた場合、メッセージが DLQ に移動することもあります。例えば、CUST_ID_005 にメッセージを送信して、顧客の情報を更新しようとすることができます。ただし、システムのデータベースから顧客が削除されたことにより、受信者が受信メッセージの処理に失敗する可能性があります。

- メッセージがDLQソフトウェアパイプラインに移動する場合、メッセージの内容の誤りと、送受信のシステム変更の2つの原因が考えられる
    - 誤ったメッセージの内容
        - 送信されたメッセージに誤りがある場合、メッセージは DLQ に移動する
        - ハードウェア、ソフトウェア、ネットワークの状態により、送信データが破損する可能性がある
        - 例えば、ハードウェアの干渉により、送信中に情報の一部がわずかに変化する。予期しないデータ破損により、受信者はメッセージを拒否または無視する可能性がある
    - 受信側のソフトウェアで送信者が気付いていない変更が行われた場合、メッセージが DLQ に移動することもある。
    - 例えば、CUST_ID_005 にメッセージを送信して、顧客の情報を更新しようとすることができる。ただし、システムのデータベースから顧客が削除されたことにより、受信者が受信メッセージの処理に失敗する可能性がある

## デッドレターキューの利点
> 通信コストの削減
通常のメッセージキューまたは標準メッセージキューは、保存期間が終了するまでメッセージの処理を続けます。これにより、メッセージを継続的に処理でき、キューがブロックされる可能性を最小限に抑えることができます。
ただし、システムが何千ものメッセージを処理する場合、エラーメッセージの数が多いと、通信オーバーヘッドコストが増加し、通信システムに負担がかかります。失敗しているメッセージについては有効期限が切れるまで処理を試みるより、処理を数回試みた後にデッドレターキューに移動する方がよいでしょう。 

> トラブルシューティングの改善
誤ったメッセージを DLQ に移動すると、デベロッパーはエラーの原因の特定に集中できます。受信者がメッセージを処理できなかった理由を調査し、修正を適用し、メッセージの配信を新たに試みることができます。
例えば、バンキングソフトウェアでは、毎日何千ものクレジットカード申請書をバックエンドシステムに送信して承認を求めることがあります。そこから、バックエンドシステムはアプリケーションを受信しますが、情報が不完全なため、すべてのアプリケーションを処理することはできません。ソフトウェアでは、IT チームが問題を解決するまでメッセージを DLQ に移動させるため、何度も試行を繰り返す必要はありません。これにより、システムはパフォーマンスの問題なしに残りのメッセージを処理して配信できます。 

- 通信コストの削減
    - 通常のメッセージキューまたは標準メッセージキューは、保存期間が終了するまでメッセージの処理を続ける。これにより、メッセージを継続的に処理でき、キューがブロックされる可能性を最小限に抑えることができる
    - ただし、システムが何千ものメッセージを処理する場合、エラーメッセージの数が多いと、通信オーバーヘッドコストが増加し、通信システムに負担がかかる
    - 失敗しているメッセージについては有効期限が切れるまで処理を試みるより、処理を数回試みた後にデッドレターキューに移動する方がよい
- トラブルシューティングの改善
    - 誤ったメッセージを DLQ に移動すると、デベロッパーはエラーの原因の特定に集中できる
    - 受信者がメッセージを処理できなかった理由を調査し、修正を適用し、メッセージの配信を新たに試みることができる
    - 例えば、バンキングソフトウェアでは、毎日何千ものクレジットカード申請書をバックエンドシステムに送信して承認を求めることがある
    - そこから、バックエンドシステムはアプリケーションを受信するが、情報が不完全なため、すべてのアプリケーションを処理することはできない
    - ソフトウェアでは、IT チームが問題を解決するまでメッセージを DLQ に移動させるため、何度も試行を繰り返す必要はない
    - これにより、システムはパフォーマンスの問題なしに残りのメッセージを処理して配信できる

## デッドレターキューはどのような場合に使用すべきか
> システムに次の問題がある場合は、デッドレターキュー (DLQ) を使用できます。 

> 順序付けされていないキュー
アプリケーションが順序に依存しない場合は、DLQ を活用できます。DLQ は誤ったメッセージ送信操作のトラブルシューティングに役立ちますが、引き続きキューをモニタリングし、失敗したメッセージを再送信するようにします。 

> FIFO キュー
先入れ先出し (FIFO) キューでは、メッセージの順序付けが重要です。すべてのメッセージは、次のメッセージを配信する前に処理する必要があります。FIFO キューではデッドレターキューを使用できますが、DLQ の実装も FIFO にする必要があります。

- 順序付けされていないキュー
    - アプリケーションが順序に依存しない場合、DLQを活用できる
    - DLQ は誤ったメッセージ送信操作のトラブルシューティングに役立ちますが、引き続きキューをモニタリングし、失敗したメッセージを再送信する
- FIFO キュー
    - 先入れ先出し (FIFO) キューでは、メッセージの順序付けが重要
    - すべてのメッセージは、次のメッセージを配信する前に処理する必要があります。FIFO キューではデッドレターキューを使用できるが、DLQ の実装も FIFO にする必要がある

## デッドレターキューの仕組み
> ほとんどの場合、デッドレターキュー (DLQ) は通常のメッセージキューと同じように機能します。誤ったメッセージは、処理してエラーの原因を調査するまで保存されます。

> 次に、DLQ のリドライブポリシーと、メッセージが DLQ に出入りする方法について説明します。

> リドライブポリシーの作成
ソフトウェアは、リドライブポリシーを参照してメッセージをデッドレターキューに移動します。リドライブポリシーは、ソフトウェアがメッセージをデッドレターキューに移動するタイミングを決定するルールで構成されています。リドライブポリシーは、主に最大再試行回数を定義することにより、ソースキューとデッドレターキューの相互作用の方法を規制します。 

> 例えば、デベロッパーが最大再試行回数を 1 回に設定した場合、システムは 1 回の試行で失敗した配信をすべて DLQ に移動します。配信の失敗の中には、一時的なネットワークの過負荷またはソフトウェアの問題が原因で発生するものもあります。これにより、DLQ に未配信のメッセージが多数送信されます。適切なバランスをとるために、デベロッパーは最大再試行回数を最適化して、メッセージを DLQ に移動する前にソフトウェアが十分な再試行を行うようにします。

- リドライブポリシーの作成
    - ソフトウェアは、リドライブポリシーを参照してメッセージをデッドレターキューに移動する
    - リドライブポリシーは、ソフトウェアがメッセージをデッドレターキューに移動するタイミングを決定するルールで構成される
    - リドライブポリシーは、主に最大再試行回数を定義することにより、ソースキューとデッドレターキューの相互作用の方法を規制する
    - 例
        - デベロッパーが最大再試行回数を 1 回に設定した場合、システムは 1 回の試行で失敗した配信をすべて DLQ に移動する
        - 配信の失敗の中には、一時的なネットワークの過負荷またはソフトウェアの問題が原因で発生するものもある
        - これにより、DLQ に未配信のメッセージが多数送信される
        - 適切なバランスをとるために、デベロッパーは最大再試行回数を最適化して、メッセージを DLQ に移動する前にソフトウェアが十分な再試行を行うようにする

    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/c9f05a4b-592e-ba6b-7fd2-7d552f018b4c.png)

※出典：[デッドレターキューの仕組みを教えてください](https://aws.amazon.com/jp/what-is/dead-letter-queue/)

> メッセージをデッドレターキューに移す
送信者と受信者の間で配信を試みると、受信者は、いくつかの理由で失敗に直面する可能性があります。 
> - メッセージが存在しないため、受信者はメッセージを受信できません。 
> - メッセージにはエラーが含まれています。 
> - メッセージがキューまたはメッセージの長さの制限を超えています。例えば、一部の受信者は特定のサイズを超えるメッセージを処理できません。 
> - メッセージの有効期間 (TTL) が期限切れになりました。TTL は、特定のデータパケットがネットワーク上でどれくらいの期間有効かを示す値です。 


> デッドレターキューからのメッセージの移動
メッセージがデッドレターキューに移動すると、デベロッパーは誤ったメッセージを調べて原因を特定します。DLQ のメッセージには、今後同様の問題が再発するのを防ぐための貴重な情報が含まれている可能性があります。デベロッパーが問題を分析して修正すると、システムはメッセージを DLQ からソースキューに移動します。これにより、送信者はメッセージの処理を続行できます。 

- 受信者は、下記の龍で失敗に直面する可能性がある
    -  メッセージが存在しないため、受信者はメッセージを受信できない
    -  メッセージにはエラーが含まれている
    -  メッセージがキューまたはメッセージの長さの制限を超過している
    -  メッセージの有効期間 (TTL) が期限切れ
- デッドレターキューからのメッセージの移動
    - メッセージがデッドレターキューに移動すると、デベロッパーは誤ったメッセージを調べて原因を特定する
    - DLQ のメッセージには、今後同様の問題が再発するのを防ぐための貴重な情報が含まれている可能性がある
    - デベロッパーが問題を分析して修正すると、システムはメッセージを DLQ からソースキューに移動する
    - これにより送信者はメッセージの処理を続行できる

# 実践
今回、下記の手順で簡単に試してみます。

1.  通常のSQSキューとDLQ用SQSキューを作成する
1.  メッセージの送信とDLQへ移動させる

構成は、下記のとおりです。

## 1.  通常のSQSキューとDLQ用SQSキューを作成する
### DLQの作成
1. AWSにサインインし、SQSに移動します
1. 「キューを作成」をクリックします
1. 下記を入力し、「キューを作成」をクリックし、DQL用のキューを作成します
    - 標準
    - 名前
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/1c37d695-085e-8ee5-f475-90131c802e34.png)

### 通常のSQSキューを作成
1. 「キューを作成」をクリックします
1. 下記を入力し、「キューを作成」をクリックし、通常のキューを作成します
    - 標準
    - 設定
        - 可視性タイムアウト:1秒（連続してメッセージを送りたいため）
    - 名前
    - デッドレターキュー：有効
        - キューの選択：上記で作成したDLQを指定
        - 最大受信回数：3回
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/0358d3dd-7f89-29bd-0871-aa4326364d40.png)
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/00d7280c-13cf-80fd-2c9e-58a226d67558.png)
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/b7f828da-5ae6-cb7f-bcfd-d0d61b13cb85.png)
1. 作成されたキューでは、デッドレターキューが設定されていることが確認できます
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/386a6c19-e472-e3a2-c11a-92fbb5768e4f.png)

## 2.  メッセージの送信とDLQへ移動させる
### メッセージをSQSに送信

1. 作成した通常のキューに移動します
1. 「メッセージを送受信」をクリックします
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/73e2fbd4-f27b-7862-5ba5-85de6c86682c.png)
1. ①メッセージを「Hello, SQS」と入力し、②「メッセージを送信」をクリックします
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/72bd8a05-34d0-63c3-eb09-cdb248386dd7.png)
1. 「利用可能なメッセージ」として1件たまりました
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/03d6a98c-6211-e2e2-f027-caf821a90165.png)

1. 最大受信回数を超えるまで、回繰り返します。この例では12回程度繰り返しました
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/04483d39-65d5-9a29-cf31-c429f15741aa.png)


### DLQに保存されたメッセージを確認する
1. DLQのメッセージキューに移動します
1. 「メッセージを送受信」をクリックします
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/c5ad1260-9e98-f2f1-dd28-65cc75515ebc.png)
1. 「メッセージをポーリング」をクリックします。4件ほど取得できました
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/d6182d0f-01fd-bc5e-2b3d-b9a2c7c80733.png)
1. この中のIDを一つ選びクリックします。ポップアップが上がりました
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/8a8eef73-722f-9e6c-95fd-3670cd6e5c1e.png)
1. 「詳細」タブをクリックすると、下記の情報が確認できます
    - 送信日時
    - 受信日時
    - メッセージ本文のMD5
    - 受信数
    - 送信者アカウントID
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/2b2c209f-feef-2787-0c57-030b74fb707a.png)


### DLQの削除
DLQに溜まったメッセージを削除します

1. ①「メッセージをすべて選択」し、②「削除」をクリックします
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/df5003d3-65c4-6760-33e4-35b952032e65.png)

1. 消えました
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/a7bd31e0-b685-701b-13ee-3dc4cdc66875.png)

# 考察
今回、DLQについて簡単なデモを試してみました。
雰囲気はつかめたと思います。


# 参考
https://aws.amazon.com/jp/what-is/dead-letter-queue/