Gérer le délai de visibilité et la nouvelle livraison

AWSBeginner
Pratiquer maintenant

Introduction

Un traitement reçoit une tâche de commande, mais s'arrête avant de l'acquitter. Vous observerez le retour de la même tâche, donnerez davantage de temps de traitement à sa livraison suivante et contrôlerez la commande réelle avant l'acquittement.

Terminez d'abord Envoyer et consommer des tâches avec SQS. Cette VM indépendante fournit son propre traitement, ses tables et ses données de référence ; les files, messages et identifiants de réception précédents ne sont pas réutilisés.

Lien avec les certifications

Ce laboratoire propose une pratique des sujets d’examen suivants.

Préparer une tâche pour une nouvelle livraison

Dans cette étape, créez une file avec un court délai de visibilité par défaut et envoyez une tâche sans la traiter.

Utilisez AWS View à côté de Terminal pour comparer les files actuelles, les résultats du traitement et les commandes stockées. Conservez les données de référence indépendantes.

Travaillez dans le répertoire du projet préparé :

cd /home/labex/project

Créez une file Standard. Son délai de visibilité par défaut est de 30 secondes, utilisé lorsqu'une requête de réception ne précise pas de valeur de remplacement. $(...) enregistre l'adresse de file sélectionnée pour les commandes suivantes.

QUEUE_URL=$(aws sqs create-queue --queue-name labex-q02-jobs --attributes VisibilityTimeout=30 --query QueueUrl --output text)

Envoyez une tâche JSON :

aws sqs send-message --queue-url "$QUEUE_URL" --message-body '{"id":"redelivery-order","quantity":3}'

Lisez le délai par défaut et les compteurs :

aws sqs get-queue-attributes --queue-url "$QUEUE_URL" --attribute-names VisibilityTimeout ApproximateNumberOfMessages ApproximateNumberOfMessagesNotVisible

Vous devez obtenir un délai de 30, un message disponible et zéro message en cours de livraison. Dans AWS View, la tâche a un nombre de réceptions de zéro, la fonction Lambda fournie n'a aucune exécution et aucune commande n'est stockée. L'envoi fait accepter la tâche par la file ; il ne la traite pas.

Observer l'expiration et une deuxième livraison

Dans cette étape, recevez une tâche, laissez-la sans acquittement et observez une deuxième livraison après l'expiration de sa visibilité.

Un message, deux livraisons

Après l'expiration de la visibilité, le même message peut être livré de nouveau avec un nouvel identifiant de réception.

Le bloc de commandes suivant constitue une expérience chronométrée. Lisez-le avant de l'exécuter. La première réception remplace le délai de visibilité par 10 secondes ; la deuxième réception immédiate ne doit rien trouver pendant que cette tâche est masquée. sleep 12 attend que l'échéance soit passée. La dernière réception accorde à la tâche qui revient une fenêtre de 120 secondes pour vous permettre de l'inspecter sans courir contre le délai court. Chaque > enregistre une réponse JSON dans un fichier différent.

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

La réception vide ne traite ni ne supprime rien. Affichez cette réponse :

cat while-hidden.json

Vous devez obtenir une réponse vide sans Messages. jq -s lit ensemble les deux réponses enregistrées : .[0] est la première livraison et .[1] la deuxième. Comparez l'identité du message et l'identifiant de livraison sans afficher les identifiants de réception :

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

Vous devez obtenir true pour same_message et new_receipt, avec un nombre de réceptions de "2". Un identifiant de message identifie le message en file à travers les tentatives. Un identifiant de réception identifie une tentative de livraison : utilisez donc toujours le dernier pour modifier la visibilité et supprimer le message.

AWS View affiche le même corps en cours de livraison, reçu deux fois, sans commande pour le moment. Il s'agit d'une véritable nouvelle livraison après une tentative non acquittée. Aucun deuxième envoi n'a été nécessaire. Les files Standard peuvent aussi livrer des doublons pour d'autres raisons ; la gestion de la visibilité ne fournit pas un traitement exactement une fois.

Exemple AWS View : la même tâche est en cours de livraison après sa deuxième livraison, sans commande stockée

Cet exemple réel montre un nombre de réceptions de deux avant le traitement métier. Les identifiants de message diffèrent entre les espaces de travail.

Prolonger la fenêtre et terminer le travail

Dans cette étape, prolongez la fenêtre de traitement de la livraison actuelle, exécutez le traitement fourni jusqu'à son terme et acquittez uniquement après avoir vérifié les données stockées.

Sélectionnez le dernier identifiant de réception depuis la deuxième réponse. jq -r écrit une chaîne brute adaptée à l'argument de commande.

RECEIPT_HANDLE=$(jq -r '.Messages[0].ReceiptHandle' second-delivery.json)

Modifiez la visibilité de cette livraison précise à 300 secondes :

aws sqs change-message-visibility --queue-url "$QUEUE_URL" --receipt-handle "$RECEIPT_HANDLE" --visibility-timeout 300

Ce nouvel intervalle commence lorsque la modification réussit. Il laisse inchangé le réglage par défaut de 30 secondes de la file et n'acquitte pas la tâche. Si la fenêtre d'inspection de 120 secondes a déjà expiré, recevez la tâche de nouveau dans second-delivery.json et sélectionnez son dernier identifiant avant de modifier la visibilité. Les tentatives supplémentaires augmentent le nombre de réceptions ; recommencez l'expérience chronométrée dans un espace de travail neuf si vous devez répéter son observation exacte de deux livraisons.

Convertissez le corps reçu, du texte JSON en objet de tâche :

jq '.Messages[0].Body | fromjson' second-delivery.json > job.json

Exécutez la fonction Lambda fournie, puis inspectez son résultat :

aws lambda invoke --function-name labex-q02-worker --payload fileb://job.json worker-response.json
cat worker-response.json

Vous devez obtenir processed: true, une quantité de 3 et un total de 850 centimes. Lisez indépendamment l'élément persisté :

aws dynamodb get-item --table-name labex-q02-orders --key '{"id":{"S":"redelivery-order"}}' --consistent-read --query Item

Uniquement après avoir confirmé le résultat réellement stocké, supprimez le message avec l'identifiant de réception actuel :

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

Vous devez obtenir le délai par défaut 30, zéro message disponible et zéro message en cours de livraison. AWS View affiche une file vide, l'entrée et le résultat réels du traitement et la commande redelivery-order/3/850. Prolonger la visibilité a réduit le risque qu'un autre traitement reçoive la tâche pendant cette tentative. Cela n'a pas rendu l'action métier idempotente ; les unités suivantes enseignent une protection durable contre les effets en double.

Supprimer la file et votre résultat

Dans cette étape, supprimez votre file, votre commande et les journaux d'exécution en conservant les ressources fournies et les données de référence.

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

Utilisez des requêtes réussies aux services pour confirmer l'absence de vos ressources et la disponibilité de la référence :

aws sqs list-queues
aws dynamodb scan --table-name labex-q02-orders --query Items
aws dynamodb scan --table-name labex-q02-reference --query Items

Aucune URL de file ni élément de commande ne reste. L'élément de référence indique toujours keep unchanged. AWS View affiche le même état de nettoyage et le traitement fourni reste disponible. Les erreurs de réseau ou d'authentification ne peuvent pas prouver la suppression.

Supprimez les fichiers locaux de livraison et de réponse :

rm -f first-delivery.json while-hidden.json second-delivery.json job.json worker-response.json

Exécutez la vérification de l'étape avant de terminer votre environnement.

Résumé

Vous avez observé une tâche SQS non acquittée redevenir disponible après l'expiration de sa visibilité, reçu le même message avec un nouvel identifiant de réception et un nombre de réceptions plus élevé, et prolongé le temps de traitement de la livraison actuelle. Vous avez vérifié une commande réellement stockée avant l'acquittement et nettoyé votre file, votre résultat et les journaux en conservant les ressources fournies.