从SQS检索多条消息

问题描述 投票:25回答:6

我在SQS中有多条消息。以下代码始终只返回一个,即使有几十个可见(不在飞行中)。 setMaxNumberOfMessages我以为会允许多次被消耗掉。我误解了吗?

 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
 }

我也尝试过使用withMaxNumberOfMessages而没有任何运气:

 receiveMessageRequest.withMaxNumberOfMessages(10);

我怎么知道队列中有消息?超过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"));

以上总是先行,并给我一个> 1的int

感谢您的输入

java amazon-web-services amazon-sqs
6个回答
32
投票

AWS API Reference Guide: Query/QueryReceiveMessage

由于队列的分布式特性,在ReceiveMessage调用上对加权随机机器集进行采样。这意味着只返回采样机器上的消息。如果队列中的消息数量很少(小于1000),则可能会获得比每次ReceiveMessage调用请求的消息少的消息。如果队列中的消息数量非常小,您可能不会在特定的ReceiveMessage响应中收到任何消息;在这种情况下,您应该重复该请求。

MaxNumberOfMessages:要返回的最大消息数。 SQS永远不会返回比此值更多的消息,但可能会返回更少的消息。


8
投票

SQS reference documentation中对这种(可以说是相当特殊的)行为有一个全面的解释。

使用SQS stores copies of messages on multiple servers之一向这些服务器发送two possible strategies和接收消息请求,

  • 短轮询:查询默认行为,仅查询服务器的子集(基于加权随机分布)。
  • 长轮询:通过将WaitTimeSeconds属性设置为非零值启用,将查询所有服务器。

在实践中,对于我的有限测试,我似乎总是像你一样得到一条短轮询的消息。


4
投票

我有同样的问题。您的队列设置的接收消息等待时间是多少?当我的时间为0时,即使队列中有8个,它也只返回1条消息。当我增加接收消息等待时间时,我得到了所有这些。对我来说似乎有点儿麻烦。


3
投票

我只是尝试相同,并借助这两个属性setMaxNumberOfMessages和setWaitTimeSeconds我能够获得10条消息。

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

o / p的快照:

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

1
投票

receiveMessageRequest.withMaxNumberOfMessages(10);

为了清楚起见,更实际的用法是添加到你的构造函数中:

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

否则,您可能只会这样做:

receiveMessageRequest.setMaxNumberOfMessages(10);

话虽这么说,改变这个将无助于原始问题。


0
投票

谢谢Caoilte!

我也遇到过这个问题。最后通过使用长轮询解决了以下配置:https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-configure-long-polling-for-queue.html

不幸的是,要使用长轮询,必须将队列创建为FIFO。我试过没有运气的标准队列。

并且在接收时,还需要设置MaxNumberOfMessages。所以我的代码就像:

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

虽然解决了,还是觉得太有线了。 AWS绝对应该为这种基本的接收操作提供更整洁的API。

从我的观点来看,AWS有许多很酷的功能,但不是很好的API。就像那些家伙一直在冲出去一样。

© www.soinside.com 2019 - 2024. All rights reserved.