我需要在1次读取中读取Amazon SQS队列中的所有消息,然后根据创建的时间戳对其进行排序并对其执行业务逻辑。
为了确保检查所有SQS主机的消息,我启用了长轮询。我这样做的方法是将队列的默认等待时间设置为10秒。 (任何大于0的值都将启用长轮询)。
然而,当我尝试读取队列时,它仍然没有给我所有的消息,我不得不做多次读取以获取所有消息。我甚至通过每个接收请求的代码启用长轮询,仍然无法正常工作。以下是我正在使用的代码。
AmazonSQSClient sqsClient = new AmazonSQSClient(new ClasspathPropertiesFileCredentialsProvider());
sqsClient.setEndpoint("sqs.us-west-1.amazonaws.com");
String queueUrl = "https://sqs.us-west-1.amazonaws.com/12345/queueName";
ReceiveMessageRequest receiveRequest = new ReceiveMessageRequest().withQueueUrl(queueUrl).withMaxNumberOfMessages(10).withWaitTimeSeconds(20);
List<Message> messages = sqsClient.receiveMessage(receiveRequest).getMessages();
我在队列中有3条消息,每次运行代码时都会得到不同的结果,有时我得到所有3条消息,有时只有1条。可见性超时我设置为2秒,只是为了消除消息变得不可见作为在阅读中没有看到它们的原因。 这是短轮询的预期行为。长轮询应该可以消除多个民意调查。我在这里做错了吗?
谢谢
答案 0 :(得分:24)
长轮询应该可以消除多个民意调查
不,当实际可用的消息时,长轮询应该消除大量的空轮询和错误的空响应。 SQS中的长时间民意调查不会等待最长的等待时间,只是寻找更多的东西返回,或者一旦发现某些东西就继续搜索。 SQS中的长时间轮询仅等待足够长时间才能找到某事:
“长轮询允许Amazon SQS服务在发送响应之前等待队列中的消息可用。因此,除非连接超时,对ReceiveMessage请求的响应将包含至少一个可用消息(如果有),并且最多包含ReceiveMessage调用中请求的最大数量。 “< / b>
- http://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-long-polling.html (强调添加)
因此,SQS找到并返回的“something”可能是所有消息(最大值)或消息的子集,因为如前所述,SQS是分布式系统。可能会在“一旦找到某些东西后尽快返回”和“在整个系统中搜索所有可能的内容,直到客户端将接受的最大消息数量”之间做出架构决策......并且,给出这些替代方案似乎是合理的,大多数应用程序更喜欢“尽可能快地尽我所能给你”的快速响应。
你不知道你实际上已经排空了一个队列,直到你从一个长的民意调查中得到一个空的回应。
答案 1 :(得分:1)
由于SQS在后端是分布式系统,因此无法保证任何特定请求都能够返回正在轮询的最大消息数。
你必须继续打电话,直到你有足够的信心,你有足够多的物品,或者队列已经清空。
答案 2 :(得分:-1)
正如Michael-sqlbot所指出的,即使在长轮询的情况下,SQS也不保证返回所有(或请求的数量)消息。长轮询只是确保您不会得到错误的空响应 - 即即使队列中有消息,您的读取请求也不会返回任何消息。
我已经围绕这个做了一些实验,发现当你增加队列中的消息数时,响应中返回的消息数接近所请求消息的数量。通常,队列中有1000多条消息,在我的实验中,我可以看到它每次都返回10条消息(这是读取请求可以返回的最大值)。实际上,对于短轮询也观察到了这种行为。即使有100多条消息,返回的消息数也不是10,尽管这些请求的很大一部分返回了10条消息。显然,这不是保证,但这是你通常会看到的。
我在我的一个博客中记录了我的实验结果 - 如果您想查看更多实验细节,请在下面发布相同的链接。
http://pragmaticnotes.com/2017/11/20/amazon-sqs-long-polling-versus-short-polling/