可視性タイムアウト、DLQ、ロングポーリング
メッセージが二重に処理されないよう可視性タイムアウトを設定し、失敗したメッセージをデッドレターキューへ送り、ロングポーリングでコストを削減します。
「可視性タイムアウト、DLQ、ロングポーリング」はCoddyKit上の無料AWS Solutions Architectレッスンです。 これはレッスン2/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはAWS Solutions Architect学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 AWS Solutions Architectコースには全4レッスンが含まれています。
可視性タイムアウトの仕組み
コンシューマーがSQSからメッセージを受信すると、そのメッセージは可視性タイムアウトと呼ばれる期間、他のすべてのコンシューマーから非表示になります。この間にコンシューマーはメッセージを処理し、その後削除します。コンシューマーがクラッシュした場合や時間内に処理を完了できなかった場合、可視性タイムアウトが切れてメッセージが再び表示され、別のコンシューマーが取得できるようになります。これが、SQSの少なくとも1回の配信保証の中核となる仕組みです。
可視性タイムアウトの設定
デフォルトの可視性タイムアウトは30秒です。0秒から12時間まで設定できます。想定される最大処理時間を十分に上回る値を設定してください。処理に最大2分かかる場合は、タイムアウトを少なくとも3~4分に設定します。また、change-message-visibilityを使用して受信単位でタイムアウトを変更することもできます。これは、特定のメッセージの処理を完了するためにさらに時間が必要だとコンシューマーが判断した場合に便利です。
# Extend visibility timeout for a specific message
aws sqs change-message-visibility \
--queue-url 'https://sqs.us-east-1.amazonaws.com/123456789012/MyQueue' \
--receipt-handle 'AQEBwJnKyrHigUMZj...' \
--visibility-timeout 300短すぎるタイムアウトと長すぎるタイムアウト
タイムアウトを短くしすぎると、コンシューマーが処理を完了する前にメッセージが再表示され、重複処理につながります。タイムアウトを長くしすぎると、元のコンシューマーがひそかに失敗した場合(正常なクリーンアップを行わないEC2インスタンスのクラッシュなど)に、別のコンシューマーがメッセージを取得するまで時間がかかります。最適なタイムアウトは、処理時間の99パーセンタイル値より少し長く、かつコンシューマーの障害から迅速に復旧できる程度に短い値です。ApproximateNumberOfMessagesNotVisible CloudWatchメトリクスを監視して、タイムアウトの問題を見つけてください。
デッドレターキューの概要
デッドレターキュー(DLQ)は、設定可能な回数(maxReceiveCount)の処理に失敗したメッセージを送る、別のSQSキューです。メッセージの受信回数がmaxReceiveCountを超えると、SQSはそのメッセージを自動的にDLQへ移動します。DLQにより、常に失敗するメッセージ(ポイズンピルメッセージ)がキューをいつまでもブロックするのを防げます。DLQ内のメッセージは、処理のバグを修正した後に調査、デバッグ、再処理できます。
デッドレターキューの設定
DLQは通常のSQSキューです(標準の送信元には標準キュー、FIFOの送信元にはFIFOキューを使用します)。送信元キューにRedrive Policyを設定し、DLQとなるキューとmaxReceiveCountのしきい値を指定します。DLQの保持期間を送信元キューより長くしてください。メッセージは遅れてDLQに到着するため、期限切れになる前に調査する時間が必要です。
aws sqs set-queue-attributes \
--queue-url 'https://sqs.us-east-1.amazonaws.com/123456789012/MyQueue' \
--attributes '{
"RedrivePolicy": "{\"deadLetterTargetArn\": \"arn:aws:sqs:us-east-1:123456789012:MyDLQ\", \"maxReceiveCount\": \"5\"}"
}'DLQの監視とアラーム設定
DLQのApproximateNumberOfMessagesVisibleメトリクスに対してCloudWatchアラームを設定します。DLQにメッセージが到着した場合は、対応が必要な処理失敗が発生したことを示します。アラームがSNS通知を送信し、オンコール担当のエンジニアに直ちにページ通知するよう設定してください。DLQのメッセージはすべて調査が必要なバグとして扱い、メッセージをひそかに蓄積させないでください。バグを修正したら、DLQ Redriveを使用してメッセージを送信元キューへ戻し、再処理します。
DLQ Redrive:メッセージの再処理
処理失敗の原因となったバグを修正したら、SQS DLQ Redriveを使用して、メッセージをDLQから送信元キューへ戻し、再処理します。コンソールには組み込みのredrive機能が用意されています。メッセージ属性でフィルタリングし、特定のメッセージだけを再処理することもできます。独自のフィルタリングロジックが必要な場合は、Lambda関数を作成してDLQをポーリングし、メッセージを送信元キューへ転送する方法もあります。
# Start DLQ message move task
aws sqs start-message-move-task \
--source-arn 'arn:aws:sqs:us-east-1:123456789012:MyDLQ' \
--destination-arn 'arn:aws:sqs:us-east-1:123456789012:MyQueue' \
--max-number-of-messages-per-second 5ショートポーリングとロングポーリング
デフォルトでは、SQSはショートポーリングを使用します。receive-message呼び出しではサーバーのランダムなサブセットが調べられ、メッセージがない場合でも直ちに結果が返されます。そのため、空のレスポンスが多数発生し、API呼び出しが無駄になります。ロングポーリングでは、メッセージが到着するまで最大20秒待機してから、空のレスポンスを返します。ロングポーリングにより、API呼び出しが減ってコストが大幅に削減され、次のポーリング周期を待つより最大20秒早くメッセージを受信できるため、レイテンシーも低下します。
ロングポーリングの有効化
ロングポーリングは、キューレベル(すべての受信呼び出しに適用)またはリクエスト単位で有効にできます。ほとんどのアプリケーションでは、ReceiveMessageWaitTimeSecondsを20に設定するキューレベルの構成が推奨されます。LambdaがイベントソースとしてSQSを使用する場合、ロングポーリングが自動的に使用されます。EC2ベースのコンシューマーでは、receive-message呼び出しのWaitTimeSecondsを設定してください。
# Enable long polling at queue level (recommended)
aws sqs set-queue-attributes \
--queue-url 'https://sqs.us-east-1.amazonaws.com/123456789012/MyQueue' \
--attributes '{"ReceiveMessageWaitTimeSeconds": "20"}'
# Or per-request
aws sqs receive-message \
--queue-url 'https://...' \
--wait-time-seconds 20 \
--max-number-of-messages 10メッセージ属性とフィルタリング
SQSメッセージにはメッセージ属性を付加できます。これはメッセージ本文とは別の、キーと値のペアによるメタデータです。属性には型(String、Number、Binary)と値があります。SQSをSNSトピックにサブスクライブしている場合は、メッセージ属性に適用するSNSサブスクリプションフィルターポリシーを使用して、関連するメッセージだけを各キューへルーティングできます。フィルタリングしない場合、すべてのSQSサブスクライバーが内容に関係なく、SNSから発行されたすべてのメッセージを受信します。
遅延キューとメッセージタイマー
遅延キューでは、送信後の遅延期間(0~15分)の間、すべての新しいメッセージが非表示になります。これは、依存する処理が先に完了するのを待つなど、コンシューマーがメッセージをすぐに処理すべきでないワークフローに便利です。送信時のDelaySecondsを使用してメッセージ単位の遅延を設定することもでき、この設定はキューレベルの遅延を上書きします。注:遅延キューはFIFOキューでは利用できません。
# Create a delay queue (5 minute delay)
aws sqs create-queue \
--queue-name 'DelayedProcessingQueue' \
--attributes '{"DelaySeconds": "300"}'クイックチェック
このレッスンで学んだ AWS Solutions Architect(SAA-C03)の概念について、理解度を確認しましょう。
レッスンのまとめ
このレッスンでは、Visibility Timeout によって処理中のメッセージが他のコンシューマーから見えなくなり、コンシューマーが失敗した場合は自動的に再配信される少なくとも1回の配信を実現できること、Dead-Letter Queues によって繰り返し失敗するメッセージを収集し、バグ修正後にデバッグや再処理を行えること、そしてLong Polling(最大20秒の待機時間)によって、Short Pollingと比べてAPIコストとレイテンシーを削減できることを学びました。次は、SNSトピックとファンアウトアーキテクチャについて説明します。
よくある質問
「可視性タイムアウト、DLQ、ロングポーリング」レッスンは無料ですか?
はい。「可視性タイムアウト、DLQ、ロングポーリング」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、AWS Solutions Architectコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 AWS Solutions Architectコースには全4レッスンが含まれています。
「可視性タイムアウト、DLQ、ロングポーリング」で何を学びますか?
メッセージが二重に処理されないよう可視性タイムアウトを設定し、失敗したメッセージをデッドレターキューへ送り、ロングポーリングでコストを削減します。 ブラウザで直接実行するハンズオンコードでAWS Solutions Architectを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
AWS Solutions Architectを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのAWS Solutions Architectは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン2/4です。
「可視性タイムアウト、DLQ、ロングポーリング」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このAWS Solutions Architectレッスンでコードを書いて実行できますか?
はい。すべてのAWS Solutions Architectレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- SQS Standard キューと FIFO キュー
- 可視性タイムアウト、DLQ、ロングポーリング
- SNS トピックとファンアウトアーキテクチャ
- SQS メッセージフィルタリングと SNS + SQS 統合