提高 Amazon SQS 性能

Improving Amazon SQS Performance

我能找到的关于 Amazon Simple Queue Service (SQS) 性能的所有信息,包括他们自己的文档,都表明获得高吞吐量需要多线程。我自己使用 JS API 和节点 12 验证了这一点。如果我创建多个线程,我在每个线程上获得大致相同的吞吐量,因此总吞吐量增加几乎是线性的。但是我 运行 在一台有很多内核的好机器上安装它。当我在单核 Lambda 中 运行 时,多线程不会提高性能,通常这是我对多线程应用程序的期望。

但有一点我不明白 - CPU 中应该没有什么事情发生,大部分时间都花在了等待网络请求上。 AWS SQS API 似乎是异步的,因为所有方法都使用回调来响应,我正在使用 Promises 来 "asyncify" 所有 API 调用,有多个任务 运行宁并发。通常使用任何类型的异步 IO 执行此操作由 Node 处理得很好,并极大地提高了吞吐量,我一直使用数据库 APIs,多个流等来执行此操作。但 SQS 绝对不是那样的,它的行为就好像它的 IO 实际上是同步的并且在网络调用上阻塞线程,这对于任何现代 API.

来说都是离谱的

有没有人在单个节点线程中成功获得高 SQS 消息吞吐量?对于 FIFO 队列(发送、接收和删除,所有这些都调用最大批处理大小为 10 的批处理方法),我看到的最大值约为 50 到 100 messages/sec。这是在 lambda 中 运行ning,即在他们自己的网络上,这仅比 运行ning 在我的笔记本电脑上通过 Internet 快一点,这是另一个令人惊讶的发现。 Amazon's documentation 说 FIFO 队列在批处理时应该支持每秒最多 3000 条消息,这对我来说很好。是否真的需要多核或虚拟 CPUs 上的多线程来实现这一点?那太荒谬了,我简直不敢相信会用到那么多 CPU,应该主要是 IO 时间,应该是异步的。

编辑:

随着我继续测试,我发现只有当每个线程处理不同的队列时,线程数量的线性提升才会发生。如果线程都在处理同一个队列,则添加线程不会有任何改善。所以它的行为就好像每个队列都被亚马逊限制了一样。但是它似乎正在限制的吞吐量远低于我发现记录为最大吞吐量的吞吐量。现在真的很困惑和失望!

Michael 对原始问题的评论是正确的。我将所有消息发送到同一个消息组。我之前一直在使用 AMQP 消息队列,其中消息将按照它们发送的顺序在队列中排序,并且它们将按该顺序分发给订阅者。但是,当多个侦听器使用 AMQP 队列时,由于不同的网络延迟,无法保证它们会按时间顺序接收。

所以这实际上是 SQS 的一个非常酷的功能,保证消息将按照它们在同一消息组中发送的顺序按时间顺序接收。就我而言,我不关心收货顺序。所以现在我在每条消息上设置一个唯一的消息组 ID,并通过增加异步消息接收循环的数量来扩展性能,仍然只在一个线程中,吞吐量是惊人的!

所以底线:如果消息的准确接收顺序对您的 FIFO 队列不重要,请将消息组 ID 设置为每条消息的唯一值,并缩放执行更多接收任务以获得最佳吞吐量性能。如果您确实需要有保证的消息顺序,看起来每秒 50 条消息左右是您所能做的最好的。