web-dev-qa-db-fra.com

Récupérer plusieurs messages de SQS

J'ai plusieurs messages dans SQS. Le code suivant always n'en renvoie qu'un, même s'il y en a des dizaines visibles (pas en vol). setMaxNumberOfMessages Je pensais que plusieurs disques pourraient être consommés en même temps .. ai-je mal compris?

 CreateQueueRequest createQueueRequest = new CreateQueueRequest().withQueueName(queueName);
 String queueUrl = sqs.createQueue(createQueueRequest).getQueueUrl();
 ReceiveMessageRequest receiveMessageRequest = new ReceiveMessageRequest(queueUrl);
 receiveMessageRequest.setMaxNumberOfMessages(10);
 List<Message> messages = sqs.receiveMessage(receiveMessageRequest).getMessages();
 for (Message message : messages) {
      // i'm a message from SQS
 }

J'ai aussi essayé d'utiliser withMaxNumberOfMessages sans un tel hasard:

 receiveMessageRequest.withMaxNumberOfMessages(10);

Comment savoir s'il y a des messages dans la file d'attente? Plus que 1?

 Set<String> attrs = new HashSet<String>();
 attrs.add("ApproximateNumberOfMessages");
 CreateQueueRequest createQueueRequest = new CreateQueueRequest().withQueueName(queueName);
 GetQueueAttributesRequest a = new GetQueueAttributesRequest().withQueueUrl(sqs.createQueue(createQueueRequest).getQueueUrl()).withAttributeNames(attrs);
 Map<String,String> result = sqs.getQueueAttributes(a).getAttributes();
 int num = Integer.parseInt(result.get("ApproximateNumberOfMessages"));

Ce qui précède est toujours exécuté avant et me donne une int qui est> 1

Merci pour votre contribution

24
sdolgy

Guide de référence de l'API AWS: Query/QueryReceiveMessage

En raison de la nature distribuée de la file d'attente, un ensemble aléatoire de machines est échantillonné lors d'un appel ReceiveMessage. Cela signifie que seuls les messages sur les machines échantillonnées sont renvoyés. Si le nombre de messages dans la file d'attente est faible (moins de 1 000), vous obtiendrez probablement moins de messages que vous n'en avez demandé par appel ReceiveMessage. Si le nombre de messages dans la file d'attente est extrêmement faible, vous risquez de ne recevoir aucun message dans une réponse ReceiveMessage particulière; Dans ce cas, vous devez répéter la demande.

et

MaxNumberOfMessages: Nombre maximal de messages à renvoyer. SQS ne renvoie jamais plus de messages que cette valeur, mais peut en renvoyer moins .

31
sdolgy

Il existe une explication détaillée de ce comportement (sans doute plutôt idiosyncratique) dans la documentation de référence SQS .

SQS stocke des copies des messages sur plusieurs serveurs et les demandes de message sont adressées à ces serveurs avec/ deux stratégies possibles ,

  • Interrogation courte: Le comportement par défaut, seul un sous-ensemble des serveurs (basé sur une distribution aléatoire pondérée) est interrogé .
  • Long Polling: Activé en définissant l'attribut WaitTimeSeconds sur une valeur autre que zéro, tous les serveurs sont interrogés .

En pratique, pour mes tests limités, il me semble toujours recevoir le même message avec une courte interrogation, tout comme vous.

8
Caoilte

J'ai eu le même problème. Quel est votre temps d'attente pour recevoir un message pour votre file d'attente? Lorsque le mien était à 0, il ne renvoyait qu'un message, même s'il y en avait 8 dans la file d'attente. Lorsque j'ai augmenté le temps d'attente du message de réception, je les ai tous obtenus. Semble un peu buggy pour moi.

4
wisbucky

J'essayais juste de la même chose et avec l'aide de ces deux attributs setMaxNumberOfMessages et setWaitTimeSeconds, j'ai pu obtenir 10 messages.

ReceiveMessageRequest receiveMessageRequest = new ReceiveMessageRequest(myQueueUrl);
                      receiveMessageRequest.setMaxNumberOfMessages(10);
                      receiveMessageRequest.setWaitTimeSeconds(20);

Instantané de o/p:

Receiving messages from TestQueue.
Number of messages:10
Message
MessageId:     31a7c669-1f0c-4bf1-b18b-c7fa31f4e82d 
...
1
niranjan

receiveMessageRequest.withMaxNumberOfMessages (10);

Soyons clairs: l’utilisation la plus pratique serait d’ajouter à votre constructeur de la manière suivante:

ReceiveMessageRequest receiveMessageRequest = new ReceiveMessageRequest(queueUrl).withMaxNumberOfMessages(10);

Sinon, vous pourriez aussi bien faire:

receiveMessageRequest.setMaxNumberOfMessages(10);

Cela étant dit, changer cela ne résoudra pas le problème initial. 

1
Marcus

Merci Caoilte!

J'ai fait face à ce problème aussi. Enfin résolu en utilisant une interrogation longue, suivez la configuration ici: https://docs.aws.Amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-configure-long-polling-for-queue.html

Malheureusement, pour utiliser une interrogation longue, vous devez créer votre file d'attente en tant que FIFO. J'ai essayé la file d'attente standard sans aucune chance.

Et lors de la réception, vous devez également définir MaxNumberOfMessages. Donc, mon code est comme:

ReceiveMessageRequest receive_request = new ReceiveMessageRequest () .withQueueUrl (QUEUE_URL) .withWaitTimeSeconds (20) .withMaxNumberOfMessages (10);

Bien que résolu, toujours se sentir trop câblé. AWS devrait certainement fournir une API plus soignée pour ce type d'opération de réception de base.

De mon point de vue, AWS possède de nombreuses fonctionnalités intéressantes, mais pas de bonnes API. Comme ces gars-là se précipitent tout le temps.

0
muyong