【发布时间】:2020-05-08 00:42:26
【问题描述】:
我能找到的关于 Amazon Simple Queue Service (SQS) 性能的所有信息,包括他们自己的文档,都表明获得高吞吐量需要多个线程。我已经使用 Node 12 的 JS API 自己验证了这一点。如果我创建多个线程,每个线程上的吞吐量大致相同,因此总吞吐量的增加几乎是线性的。但我在一台有很多内核的好机器上运行它。当我在单核上运行 Lambda 时,多线程并不能提高性能,这通常是我对多线程应用程序的期望。
但这就是我不明白的地方——CPU 的方式应该很少发生,大部分时间都花在等待网络请求上。 AWS SQS API 似乎是异步的,因为所有方法都对响应使用回调,并且我使用 Promises 来“异步化”所有 API 调用,同时运行多个任务。通常,使用任何类型的异步 IO 执行此操作都由 Node 处理得很好,并且极大地提高了吞吐量,我一直使用数据库 API、多个流等来执行此操作。但是 SQS 绝对不是那样的,它的行为好像它的IO 实际上是网络调用上的同步和阻塞线程,这对于任何现代 API 来说都是令人发指的。
有没有人成功地在单个节点线程中获得高 SQS 消息吞吐量?对于 FIFO 队列(发送、接收和删除,所有这些都在调用最大批处理大小为 10 的批处理方法),我看到的最大值约为 50 到 100 条消息/秒。这是在 lambda 中运行的,即在他们自己的网络上,它只比通过 Internet 在我的笔记本电脑上运行它稍微快一点,这是另一个令人惊讶的发现。 Amazon's documentation 说 FIFO 队列在批处理时应该支持每秒最多 3000 条消息,这对我来说很好。真的需要多个内核或虚拟 CPU 上的多个线程来实现这一点吗?那太可笑了,我简直不敢相信会使用那么多CPU,应该主要是IO时间,应该是异步的。
编辑:
随着我继续测试,我发现只有在每个线程处理不同的队列时才会出现线程数的线性改进。如果线程都在处理同一个队列,那么添加线程并没有改善。所以它表现得好像每个队列都被亚马逊限制了。但是它似乎被限制的吞吐量远低于我发现的最大吞吐量。现在真的很困惑和失望!
【问题讨论】:
-
您正在以足够高的速率将消息驱动到 FIFO 队列中,或者它已经填充了足够多的消息,大概可以对此进行测试。另请注意,如果延迟平均为 20 毫秒,则该文档页面上的 cmets 指示“单个线程在单个连接上的最大吞吐量平均为 50 TPS”。
-
@jarmod 是的,生产者率通常要高得多,但我已经尝试同时运行生产者和消费者,并在启动消费者之前完成所有发送。我确实看到了您现在所指的评论,我想这就是我要反对的。我对他们关于需要更多线程的解释并不满意,因为每个线程都在等待 Web 请求/响应。线程很昂贵,我不明白为什么任何现代 API 都会阻塞等待 Web 请求响应的线程,而不是在同一个线程上发出多个并发的异步请求。
-
@reads0520 文档在非常随意/不精确的意义上使用“线程”,指的是不相互阻塞的不同消费者的数量(在消费者端代码中),无论是由于多个进程、多个线程或触发多个异步请求所允许的并发性...但除非您使用不同的 MessageGroupID,否则 FIFO 队列受到消息严格排序的限制——消费者 2 将在消费者 1 之前接收任何消息处理它已经收到的内容并删除这些消息......否则你没有得到严格的排序。
-
@Michael 谢谢,这很有意义!我会根据你的cmets来回答这个问题...
标签: node.js multithreading amazon-web-services message-queue amazon-sqs