【问题标题】:AWS SQS - Relationship between number of queue consumers and the number of in-flight messagesAWS SQS - 队列消费者数量与传输中消息数量之间的关系
【发布时间】:2019-08-04 23:36:02
【问题描述】:

我有一个标准的 AWS SQS 队列,并且有多个 EC2 实例(~2K)以 2 秒的间隔主动轮询该队列。 我正在使用 AWS Java SDK 来轮询队列,并使用 ReceiveMessageRequest 和一条消息来响应每个请求。

我的期望是,在 SQS 控制台中显示的 正在运行的消息数是消费者收到但尚未从队列中删除的消息数(即,它是活动消息的数量正在处理中)。但问题是飞行中消息的数量比我瞬间的消费者数量要少得多。正如我所提到的,我有大约 2K 消费者,但我只看到飞行中的消息在 aprox 中计数。 300-600 范围。

我的假设是错误的,即正在运行的消息等于当前正在处理的消息数量。 SQS/EC2 或 SQS Java SDK 中是否有任何限制可以限制即时处理的消息数量?

【问题讨论】:

  • 你的假设是正确的。您使用的是标准队列还是 FIFO 队列?
  • @JohnRotenstein 这是一个标准队列

标签: amazon-web-services amazon-sqs aws-java-sdk


【解决方案1】:

这可能表明您的主机未主动处理消息的时间超出预期。

在您的示例中,2000 个消费者以 2 秒的间隔轮询,但在飞行消息中仅达到 600 条 - 一些非常粗略的数学 (600/2000=0.3) 表明您的主机仅花费 30% 的时间实际处理。在最简单的情况下,如果一条消息的轮询/处理/删除只需要 600 毫秒,就会发生这种情况,从删除一条消息到接收下一条消息之间平均有 1400 毫秒的空闲时间。

进行大容量消息处理的一个很好的模式是从线程池的角度来考虑消息处理 - 一个用于获取消息,一个用于处理,一个用于删除(具有本地 in-内存队列在每个池之间转换消息)。每个池都有一个非常特定的目的,并且可以更轻松地调整以很好地完成该目的:

  • 有足够的提取器(使用批处理 ReceiveMessage API)以保持处理器畅通
  • 限制 fetcher 和处理器之间的内存队列的大小,以便单个主机不会将过多的消息发送出去(阻止其他主机处理它们)
  • 添加主机可以处理的尽可能多的处理器线程
  • 保留有关处理所需时间的指标,并提供在超过特定时间阈值(与可见性超时相关)时中止处理的能力
  • 使用足够的删除器来跟上处理速度(也使用批量 DeleteMessage API)

通过记录每个阶段的指标以及每个阶段之间的内存队列,您可以轻松查明瓶颈所在并进一步微调系统。

其他需要考虑的事项:

  • Use long polling - 在 ReceiveMessage API 中设置 WaitTimeSeconds 属性以尽量减少空响应
  • 当您看到低吞吐量时,请确保您的队列已饱和 - 如果队列中的项目很少且处理器很多,那么其中许多处理器将处于空闲状态等待消息。
  • 不要按时间间隔轮询 - 在您处理完之前的消息后立即轮询。
  • 使用 batching 一次请求/删除多条消息,减少往返 SQS 调用所花费的时间

【讨论】:

    【解决方案2】:

    一般来说,随着消费者数量的增加,正在传输的消息数量也会增加——每个消费者每次读取请求最多可以请求 10 条消息——但实际上,如果每个消费者总是请求 10 条,他们将获得0-10 条消息,尤其是在消息数量较少而消费者数量较多的情况下。

    所以您的想法或多或少是正确的,但是您无法根据当前运行的消费者数量准确预测在任何给定时间有多少消息正在传输,但两者之间存在不精确的相关性.

    【讨论】:

    • 另外一个考虑因素是,in-flight 属性的名称ApproximateNumberOfMessagesNotVisible 意味着缺乏精确性。
    猜你喜欢
    • 2016-07-01
    • 1970-01-01
    • 2013-05-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-06
    • 1970-01-01
    • 2013-03-09
    相关资源
    最近更新 更多