はじめに
ワーカーが注文ジョブを受信しましたが、処理済みとして確認する前に停止します。同じジョブが戻ることを観察し、次の配信により長い処理時間を与え、実際の注文を確認してから処理済みとして確認します。
先に SQS でジョブを送信して消費する を完了してください。この独立した VM は、独自のワーカー、テーブル、参照データを提供します。以前のキュー、メッセージ、レシートハンドルは再利用しません。
認定試験との関連
このラボでは、次の試験トピックに関連する実践的な演習を行います。
- Solutions Architect – Associate (SAA-C03) · タスク 2.1: SQS の可視性タイムアウト、再配信、受信ハンドル。
- Developer – Associate (DVA-C02) · タスク 1.1: SQS の可視性タイムアウト、再配信、受信ハンドル。
- DevOps Engineer – Professional (DOP-C02) · タスク 5.1: 基礎演習:SQS の可視性タイムアウト、再配信、受信ハンドル。
- Solutions Architect – Professional (SAP-C02) · タスク 2.4: 基礎演習:SQS の可視性タイムアウト、再配信、受信ハンドル。
再配信を観察するジョブを準備する
このステップでは、短いデフォルト可視性タイムアウトのキューを作成し、ジョブを処理せずに送信します。
Terminal の隣で AWS View を使い、現在のキュー、ワーカーの結果、保存された注文を比較します。無関係な参照データを保持してください。
準備されたプロジェクトディレクトリで作業します。
cd /home/labex/project
Standard キューを作成します。デフォルトの可視性タイムアウトは 30 秒で、受信リクエストが上書き値を指定しない場合に使われます。$(...) は、後のコマンドのために選択されたキューアドレスを保存します。
QUEUE_URL=$(aws sqs create-queue --queue-name labex-q02-jobs --attributes VisibilityTimeout=30 --query QueueUrl --output text)
JSON ジョブを 1 件送ります。
aws sqs send-message --queue-url "$QUEUE_URL" --message-body '{"id":"redelivery-order","quantity":3}'
デフォルトタイムアウトと件数を読み取ります。
aws sqs get-queue-attributes --queue-url "$QUEUE_URL" --attribute-names VisibilityTimeout ApproximateNumberOfMessages ApproximateNumberOfMessagesNotVisible
タイムアウトは 30、利用可能なメッセージは 1 件、処理中のメッセージは 0 件となるはずです。AWS View では、ジョブの受信回数は 0 で、提供された Lambda には実行がなく、保存された注文もありません。送信はジョブをキューに受け付けるものであり、処理するものではありません。
期限切れと 2 回目の配信を観察する
このステップでは、ジョブを受信し、処理済みとして確認しないままにして、可視性の期限切れ後に 2 回目の配信を観察します。

可視性が期限切れになると、同じメッセージが新しいレシートハンドルで再び配信される場合があります。
以下のコマンドブロックは、時間を決めて行う 1 つの実験です。実行前に読んでください。最初の受信は、可視性を 10 秒に上書きします。直後の 2 回目の受信では、そのジョブが非表示のため、何も見つからないはずです。sleep 12 は期限が過ぎるまで待ちます。最後の受信は、戻ったジョブに 120 秒の時間枠を与え、短いタイムアウトに追われずに確認できるようにします。各 > は、JSON レスポンスを別のファイルに保存します。
aws sqs receive-message --queue-url "$QUEUE_URL" --max-number-of-messages 1 --visibility-timeout 10 --message-system-attribute-names ApproximateReceiveCount --output json > first-delivery.json
aws sqs receive-message --queue-url "$QUEUE_URL" --max-number-of-messages 1 --wait-time-seconds 0 --output json > while-hidden.json
sleep 12
aws sqs receive-message --queue-url "$QUEUE_URL" --max-number-of-messages 1 --visibility-timeout 120 --message-system-attribute-names ApproximateReceiveCount --output json > second-delivery.json
空の受信は、何も処理したり削除したりしません。そのレスポンスを表示します。
cat while-hidden.json
Messages がない空のレスポンスが返るはずです。jq -s は、保存した 2 つのレスポンスを一緒に読み取ります。.[0] は最初の配信、.[1] は 2 回目の配信です。ハンドルを表示せずに、メッセージの識別情報と配信のレシートを比較します。
jq -s '{
same_message: (.[0].Messages[0].MessageId == .[1].Messages[0].MessageId),
new_receipt: (.[0].Messages[0].ReceiptHandle != .[1].Messages[0].ReceiptHandle),
receive_count: .[1].Messages[0].Attributes.ApproximateReceiveCount
}' first-delivery.json second-delivery.json
same_message と new_receipt は true、受信回数は "2" となるはずです。メッセージ ID は、試行をまたいでキュー内のメッセージを識別します。レシートハンドルは 1 回の配信試行を識別するため、可視性の変更と削除には常に最新のハンドルを使ってください。
AWS View には、同じ本文が処理中として表示され、受信回数は 2 回、注文はまだありません。これは、処理済みとして確認されなかった試行に続く実際の再配信です。2 回目の送信は不要でした。Standard キューは、他の理由でも重複配信する場合があります。可視性の管理は、厳密に 1 回の処理を提供しません。

この実際の例は、業務処理前の受信回数 2 を示します。メッセージ識別子は作業ディレクトリごとに異なります。
処理時間を延長して作業を完了する
このステップでは、現在の配信の処理時間を延長し、提供されたワーカーを完了させ、保存データを確認した後にだけ処理済みとして確認します。
2 回目のレスポンスから最新のレシートハンドルを選択します。jq -r は、コマンド引数に適したプレーンな文字列を出力します。
RECEIPT_HANDLE=$(jq -r '.Messages[0].ReceiptHandle' second-delivery.json)
この特定の配信の可視性を 300 秒に変更します。
aws sqs change-message-visibility --queue-url "$QUEUE_URL" --receipt-handle "$RECEIPT_HANDLE" --visibility-timeout 300
この新しい期間は、変更が成功したときに始まります。キューのデフォルトである 30 秒の設定は変わらず、ジョブを処理済みとして確認することもありません。120 秒の確認時間がすでに期限切れの場合は、可視性を変更する前にジョブを再び second-delivery.json に受信し、最新のハンドルを選択してください。追加の試行は受信回数を増やします。正確に 2 回の配信の観察を繰り返す必要がある場合は、新しい作業環境で時間を決めた実験を再実行してください。
受信した本文を JSON テキストからジョブオブジェクトに変換します。
jq '.Messages[0].Body | fromjson' second-delivery.json > job.json
提供された Lambda を実行し、結果を確認します。
aws lambda invoke --function-name labex-q02-worker --payload fileb://job.json worker-response.json
cat worker-response.json
processed: true、数量 3、合計 850 セントが返るはずです。永続化されたアイテムを独立して読み取ります。
aws dynamodb get-item --table-name labex-q02-orders --key '{"id":{"S":"redelivery-order"}}' --consistent-read --query Item
実際の保存結果を確認した後にだけ、現在のレシートハンドルで削除します。
aws sqs delete-message --queue-url "$QUEUE_URL" --receipt-handle "$RECEIPT_HANDLE"
aws sqs get-queue-attributes --queue-url "$QUEUE_URL" --attribute-names VisibilityTimeout ApproximateNumberOfMessages ApproximateNumberOfMessagesNotVisible
デフォルトタイムアウトは 30、利用可能なメッセージも処理中のメッセージも 0 件となるはずです。AWS View には、空のキュー、実際のワーカーの入力と結果、注文 redelivery-order/3/850 が表示されます。可視性の延長は、この試行の処理中に別のワーカーがジョブを受信する可能性を下げました。業務操作を冪等にしたわけではありません。後のユニットで、重複した効果に対する永続的な保護を学びます。
キューと所有する結果を削除する
このステップでは、提供された準備リソースと参照データを保持しながら、自分のキュー、注文、実行ログを削除します。
aws sqs delete-queue --queue-url "$QUEUE_URL"
aws dynamodb delete-item --table-name labex-q02-orders --key '{"id":{"S":"redelivery-order"}}'
aws logs delete-log-group --log-group-name /aws/lambda/labex-q02-worker
成功するサービスクエリで、不在と参照リソースの利用可能な状態を確認します。
aws sqs list-queues
aws dynamodb scan --table-name labex-q02-orders --query Items
aws dynamodb scan --table-name labex-q02-reference --query Items
キュー URL や注文アイテムは残りません。参照アイテムには引き続き keep unchanged があります。AWS View にも同じ後片付け状態が表示され、提供されたワーカーは利用可能なままです。ネットワークエラーや認証エラーは削除の証拠になりません。
ローカルの配信ファイルとレスポンスファイルを削除します。
rm -f first-delivery.json while-hidden.json second-delivery.json job.json worker-response.json
環境を終了する前に、このステップの検証を実行してください。
まとめ
処理済みとして確認されなかった SQS ジョブが可視性の期限切れ後に利用可能になることを観察し、同じメッセージを新しいレシートハンドルと増えた受信回数で受信して、現在の配信の処理時間を延長しました。処理済みとして確認する前に実際の保存された注文を確認し、提供されたリソースを保持しながら、自分のキュー、結果、ログを後片付けしました。



