AWS SQS-队列使用者数量与运行中消息数量之间的关系

时间:2019-03-14 06:37:09

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

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

我的期望是,在SQS控制台中显示的航班中的消息数量是使用者收到的,尚未从队列中删除的消息数量(即,活动消息的数量)正在处理中)。但是问题在于,飞行中消息的数量比我瞬间拥有的消费者数量少得多。正如我提到的那样,我有大约2K的消费者,但我只看到机顶盒中包含机内消息。 300-600范围。

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

2 个答案:

答案 0 :(得分:2)

通常来说,随着消费者数量的增加,运行中的消息数量也会增加-每个消费者每次读取请求最多可以请求10条消息-但实际上,如果每个消费者总是请求10条消息,他们将获得从0到10条消息的任何地方,尤其是在消息数少而使用者数多的情况下。

因此,您的想法或多或少是正确的,但是您无法根据当前运行的消费者数量准确地准确预测任何给定时间正在发送多少条消息,但是两者之间存在不精确的关联

答案 1 :(得分:1)

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

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

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

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

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

要考虑的其他事项:

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