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?

【コツコツAWS】Amazon SQS② - DLQでのエラーメッセージ処理 -

0
Posted at

Amazon SQSに関して、勉強したことを残します。
今回はDLQ (Dead Letter Queue)を使って、エラーを起こすメッセージが入った際に、処理が繰り返されるのを防ぐ方法について確認します。
SQSに関する前回の記事はこちら。

DLQが無いと…

前回の記事ではAmazon SQSの基本的な使い方を確認するために、以下のような題材で実装を行いました。

① S3に文章(テキストファイル)格納
 ↓
② AWS Lambdaを使って各行の文章をSQSへ登録
 ↓
③ Amazon SQSでメッセージ保持
 ↓
④ AWS LambdaがSQSからメッセージ受け取って処理

今回も上記の題材を使って、まずエラーが発生した場合の挙動を確認します。
④のConsumer側のLambda関数に以下のような意図的なエラーを発生させるコードを追加するだけです。

エラー発生を加えたConsumer関数
import json

def lambda_handler(event, context):

    for record in event["Records"]:

        msg = json.loads(record["body"])
        text = msg["text"]
        # この部分を追加 (brokenに対しエラー発生させる)
        if "broken" in text:
            raise Exception("simulate failure")

        word_count = len(text.split())

        print(f"Line {msg['line_number']} words: {word_count}")

    return {"statusCode": 200}

上記のエラー処理を追加して、実際にbrokenという行を含むファイルをS3に保存すると、Consumer側のCloudWatchに以下のようなエラーメッセージが何度も発生します。

error message
[ERROR] Exception: simulate failure
Traceback (most recent call last):
  File "/var/task/lambda_function.py", line 11, in lambda_handler
    raise Exception("simulate failure")

また、SQSのコンソールでは使用しているキューの「処理中のメッセージ」が1から減らなくなります。

image.png

メッセージが減らないのは、Consumerがメッセージを取得 → エラーのため削除されず → 可視性タイムアウトの時間が経過 → 別のConsumerがメッセージを取得 → エラー の繰り返しになっているためです。

メッセージの処理はキューで設定した「可視性タイムアウト」の間隔で行われるため、CloudWatchの方にエラーメッセージが何度も出ています。

このようにエラーによってメッセージが処理されないと、そのまま何度も処理が繰り返されるため、ファイル処理としては良くありません。

今回のようなお試しであれば、キューのページからメッセージを削除してしまえばよいですが、実際の運用ではそうはいきません。
そこでDLQを設定します。

DLQの導入

まずDLQ用のキューを作成します。
作成方法は通常のキューとほぼ同じで、異なるのはデッドレターキューとして使用できるよう有効化するだけです。(今回は同一アカウント・リージョンのキューであればDLQとして使用できるよう設定)
コンソールでは↓のような選択をしました。

image.png

次に元々のテキスト処理用のキューの設定を変更。(下図)
上で作ったキューをDLQとして設定し、何回失敗したらDLQに送るかを「最大受信数」で指定すれば完了です。

image.png

これでDLQの導入は完了しました。
先程のようにbrokenの行を含むファイルを入力してしばらく待つと、処理の失敗したメッセージがDLQの方に移動して、テキスト処理用のキューの「処理中のメッセージ」が0になり、DLQ用のキューの「利用可能なメッセージ」が1になります。

image.png

DLQのキューを選択し、「メッセージを送受信」の項目からメッセージを確認すると、確かにbrokenの入ったメッセージがDLQに移動しているのが確認できました。

DLQに入ったメッセージ
{"bucket": "<テキストを入れたバケット>", "key": "***.txt", "line_number": 1, "text": "broken"}

DLQの使いどころ

実際の運用では、DLQは単なるごみ箱ではなく、失敗した処理を保管して失敗の原因を確認し、再投入するための避難場所のようです。
CloudWatch AlarmでApproximateNumberOfMessagesVisibleをメトリクスとすれば、メッセージが一定数溜まったタイミングで通知を送ることもできます。
通知を元にメッセージの中身からエラーの原因を解析して、処理やデータを修正することになるのかと思います。

まとめ

今回はAmazon SQSに関して、処理が失敗したときの挙動とDLQに関して確認しました。
作った処理の全てが問題なく動くことはあり得ないので、キューを作る時はDLQも併せて作ることが必須と言えそうです。

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?