【问题标题】:Amazon SQS Long Polling not returning all messagesAmazon SQS 长轮询未返回所有消息
【发布时间】:2014-02-01 17:02:48
【问题描述】:

我需要在 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 秒,只是为了消除消息变得不可见作为没有在阅读中看到它们的原因。 这是短轮询的预期行为。长轮询应该消除多次轮询。我在这里做错了什么吗?

谢谢

【问题讨论】:

    标签: java amazon-web-services queue long-polling amazon-sqs


    【解决方案1】:

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

    你只需要继续打电话,直到你有足够的信心,你有尽可能多的项目,或者队列已被清空。

    【讨论】:

    • 那么长轮询在这个用例中并没有真正的帮助。尽管它正在查看所有消息托管服务器,因此确实知道队列中的所有消息,但它有时可以返回消息的子集。听起来有些不对劲。
    • Kaputabo,长轮询并非旨在帮助此用例。这是事实。事实上,听起来 SQS 并不是为您的用例而设计的。也许您应该考虑使用 DynamoDB?
    【解决方案2】:

    长轮询应该消除多次轮询

    不,长轮询应该在消息实际可用时消除大量空轮询和虚假空响应。 SQS 中的长轮询不会坐下来等待最长的等待时间,只是为了寻找更多返回的东西,或者在找到东西后继续搜索。 SQS 中的长轮询只等待足够长的时间来找到一些东西

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

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

    因此,SQS 找到并返回的“某物”可能是所有消息(最多为您的最大值),或消息的子集,因为如前所述,SQS 是一个分布式系统。可能需要在“一旦我们发现某些东西就尽快返回”和“在整个系统中搜索所有可能的信息,直到客户端可以接受的最大消息数”之间做出架构决策……并且,给定对于这些替代方案,大多数应用程序更喜欢“尽可能快地给我任何东西”这样的更快响应似乎是合理的。

    在您从长轮询中得到空响应之前,您不知道您实际上已经排空了队列。

    【讨论】:

    • 从长轮询中获得空返回并不能保证队列为空。当您询问队列中的消息数量时,一个更好的空虚指标是返回 0,但这也不能保证。
    • @tster 我从来没有遇到过这样的情况,即尽管队列中有消息,但长轮询返回 0 条消息,尽管这在理论上是可能的——但是,这确实与记录在案的断言相矛盾,即长轮询响应“将至少包含一条可用消息”(如果有)。如果发生这种情况,应该是例外。
    • 长轮询的等待时间应该是多少?我们怎么知道设置的时间间隔足以让 SQS 保证不再有消息?
    【解决方案3】:

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

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

    我已经在我的一个博客中记录了我的实验结果 - 在下面发布一个相同的链接,以防您想查看实验的更多详细信息。

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

    【讨论】:

    • @Mortiz 我已经用更多细节修改了我的帖子。你们能否再次审查并根据需要进行投票
    猜你喜欢
    • 1970-01-01
    • 2021-01-17
    • 2013-10-17
    • 1970-01-01
    • 2022-01-13
    • 1970-01-01
    • 2014-11-10
    • 2016-03-05
    • 2015-09-09
    相关资源
    最近更新 更多