Amazon SQS长轮询不返回所有邮件

我需要在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 messages = sqsClient.receiveMessage(receiveRequest).getMessages(); 

我在队列中有3条消息,每次运行代码时都得到不同的结果,有时候我得到所有3条消息,有时只有1条。可见性超时我设置为2秒,只是为了消除消息变得不可见的原因因为没有在阅读中看到它们。 这是短轮询的预期行为。 长轮询应该可以消除多个民意调查。 我在这里做错了吗?

谢谢

长轮询应该可以消除多个民意调查

不,当实际可用的消息时,长轮询应该消除大量的空轮询和错误的空响应。 SQS中的长时间民意调查不会等待最长的等待时间,只是寻找更多要返回的东西,或者一旦发现某些东西就继续搜索。 在SQS中进行长时间的民意调查只需要等待很长时间才能找到:

长轮询允许Amazon SQS服务在发送响应之前等待队列中的消息可用。 因此,除非连接超时,否则对ReceiveMessage请求的响应将包含至少一个可用消息(如果有),并且最多包含ReceiveMessage调用中请求的最大数量。

http://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-long-polling.html (重点补充)

因此,SQS找到并返回的“某些东西”可能是所有消息(达到最大值)或消息的子集,因为正如已经提到的,SQS是一个分布式系统。 可能会在“一旦我们找到某些东西后尽快返回”和“在整个系统中搜索所有可能的内容,直到客户端将接受的最大消息数量”之间做出架构决策……并且,给出这些替代方案似乎是合理的,大多数应用程序更喜欢“尽可能快地尽我所能给你”的更快响应。

你不知道你实际上已经排空了一个队列,直到你从一个长的民意调查中得到一个空的回应。

由于SQS在后端是分布式系统,因此无法保证任何特定请求都能够返回正在轮询的最大消息数。

你必须继续打电话,直到你有足够的信心,你有足够多的项目,或者队列已经清空。

正如Michael-sqlbot所指出的,即使在长轮询的情况下,SQS也不保证返回所有(或请求的数量)消息。 长轮询只是确保您不会得到错误的空响应 – 即即使队列中有消息,您的读取请求也不会返回任何消息。

我围绕这个做了一些实验,发现当你增加队列中的消息数时,响应中返回的消息数接近所请求消息的数量。 通常,队列中有1000多条消息,在我的实验中,我可以看到它每次都返回10条消息(这是读取请求可以返回的最大值)。 实际上,对于短轮询也观察到了这种行为。 即使有100多条消息,返回的消息数也不是10,尽管这些请求的很大一部分返回了10条消息。 显然,这不是保证,但这是你通常会看到的。

我在我的一个博客中记录了我的实验结果 – 如果您想查看实验的更多细节,请在下面发布相同的链接。

http://pragmaticnotes.com/2017/11/20/amazon-sqs-long-polling-versus-short-polling/