web-dev-qa-db-fra.com

Meilleur moyen de déplacer des messages hors DLQ dans Amazon SQS?

Quelle est la meilleure pratique pour déplacer les messages d'une file d'attente de lettres mortes vers la file d'attente d'origine dans Amazon SQS?

Serait-ce

  1. Recevez un message de DLQ
  2. Écrire un message dans la file d'attente
  3. Supprimer le message de DLQ

Ou existe-t-il un moyen plus simple? 

En outre, AWS disposera-t-il éventuellement d'un outil dans la console pour déplacer les messages hors de la liste DLQ?

35
Matt Dell

Cela ressemble à votre meilleure option. Il est possible que votre processus échoue après l'étape 2. Dans ce cas, vous finirez par copier le message deux fois, mais votre application devrait quand même gérer la remise des messages (ou ne pas s'en soucier).

8
Dave

Voici un petit hack. Ce n'est certainement pas la meilleure option ou recommandée.

  1. Définissez la file d'attente SQS principale comme DLQ pour la DLQ réelle avec Réception maximale égale à 1.
  2. Voir le contenu dans DLQ (Cela déplacera les messages dans la file principale car il s'agit de la DLQ pour la DLQ réelle)
  3. Supprimez le paramètre pour que la file principale ne soit plus la DLQ de la DLQ réelle.
61
Rajkumar

Il n'est pas nécessaire de déplacer le message car il comportera de nombreux autres problèmes, tels que des messages en double, des scénarios de récupération, un message perdu, une vérification de déduplication, etc.

Voici la solution que nous avons mise en place -

En général, nous utilisons le DLQ pour les erreurs transitoires, pas pour les erreurs permanentes. Alors pris ci-dessous l'approche -

  1. Lire le message de DLQ comme une file d'attente normale 

    Avantages
    • Pour éviter le traitement des messages en double 
    • Meilleur contrôle sur DLQ - Comme je l'ai fait avec une vérification, à traiter uniquement lorsque la file d'attente normale est complètement traitée.
    • Échelonnez le processus en fonction du message sur DLQ
  2. Suivez ensuite le même code que la file d'attente habituelle.

  3. Plus fiable en cas d’abandon du travail ou d’arrêt du processus en cours de traitement (par exemple, instance tuée ou processus arrêté)

    Avantages
    • Code réutilisabilité
    • La gestion des erreurs
    • Récupération et relecture du message
  4. Étendez la visibilité des messages de sorte qu'aucun autre thread ne les traite.

    Avantage
    • Évitez de traiter le même enregistrement par plusieurs threads.
  5. Supprimez le message uniquement en cas d'erreur permanente ou de réussite.

    Avantage
    • Continuez le traitement jusqu'à ce que nous obtenions une erreur transitoire.
9
Ash

ici:

import boto3
import sys
import Queue
import threading

work_queue = Queue.Queue()

sqs = boto3.resource('sqs')

from_q_name = sys.argv[1]
to_q_name = sys.argv[2]
print("From: " + from_q_name + " To: " + to_q_name)

from_q = sqs.get_queue_by_name(QueueName=from_q_name)
to_q = sqs.get_queue_by_name(QueueName=to_q_name)

def process_queue():
    while True:
        messages = work_queue.get()

        bodies = list()
        for i in range(0, len(messages)):
            bodies.append({'Id': str(i+1), 'MessageBody': messages[i].body})

        to_q.send_messages(Entries=bodies)

        for message in messages:
            print("Coppied " + str(message.body))
            message.delete()

for i in range(10):
     t = threading.Thread(target=process_queue)
     t.daemon = True
     t.start()

while True:
    messages = list()
    for message in from_q.receive_messages(
            MaxNumberOfMessages=10,
            VisibilityTimeout=123,
            WaitTimeSeconds=20):
        messages.append(message)
    work_queue.put(messages)

work_queue.join()
7
Brian Dilley

J'ai écrit un petit script python pour le faire, en utilisant boto3 lib:

conf = {
  "sqs-access-key": "",
  "sqs-secret-key": "",
  "reader-sqs-queue": "",
  "writer-sqs-queue": "",
  "message-group-id": ""
}

import boto3
client = boto3.client(
    'sqs',
        aws_access_key_id       = conf.get('sqs-access-key'),
        aws_secret_access_key   = conf.get('sqs-secret-key')
)

while True:
    messages = client.receive_message(QueueUrl=conf['reader-sqs-queue'], MaxNumberOfMessages=10, WaitTimeSeconds=10)

    if 'Messages' in messages:
        for m in messages['Messages']:
            print(m['Body'])
            ret = client.send_message( QueueUrl=conf['writer-sqs-queue'], MessageBody=m['Body'], MessageGroupId=conf['message-group-id'])
            print(ret)
            client.delete_message(QueueUrl=conf['reader-sqs-queue'], ReceiptHandle=m['ReceiptHandle'])
    else:
        print('Queue is currently empty or messages are invisible')
        break

vous pouvez obtenir ce script dans ce link

ce script peut en principe déplacer des messages entre des files d'attente arbitraires. et il supporte les files d'attente fifo ainsi que vous pouvez fournir le champ message_group_id.

1
linehrr

Il existe un autre moyen de réaliser cela sans écrire une seule ligne de code . Considérons que le nom actuel de votre file d'attente est SQS_Queue et que la DLQ pour ce nom est SQS_DLQ . Suivez maintenant ces étapes:

  1. Définissez SQS_Queue en tant que dlq de SQS_DLQ. Depuis SQS_DLQ est déjà un dlq de SQS_Queue. Maintenant, les deux agissent comme le dlq de l'autre.
  2. Définissez le nombre maximal de réceptions de votre SQS_DLQ sur 1.
  3. Lisez maintenant les messages de la console SQS_DLQ. Étant donné que le nombre de réception de message est égal à 1, il envoie tout le message à son propre fichier dlq, qui correspond à votre file d'attente SQS_Queue.
0
Priyanka Agarwal