如何使用消息队列在 Node JS 中执行长事件处理?

How to perform long event processing in Node JS with a message queue?

我正在使用 Google Pub/Sub 作为消息队列在 Node JS 中构建电子邮件处理管道。消息队列有一个限制,它需要在 10 分钟内确认已发送的消息。但是,它发送到 Node JS 服务器的作业可能需要一个小时才能完成。所以同一个工作可能 运行 多次,直到其中一个完成。我担心这会阻塞 Node JS 事件循环并降低服务器速度。

查找附件中的体系结构图。我的问题是:

  1. 我是否应该使用消息队列来启动这个耗时 运行 的作业,因为消息队列预计会在 10 分钟内得到响应,或者我应该考虑其他架构吗?
  2. 如果启动了多个这样的作业,我是否应该担心Node JS事件循环被阻塞。每个作业基本上都是通过 MongoDB 游标迭代创建数十万封电子邮件。

嗯,听起来你要么不应该使用那个队列(超时你不能改变)要么你应该把你的工作分解成一些在超时之前很容易完成的事情。这听起来像是您只需要将工具与工作要求相匹配即可。如果该队列不符合您的要求,您可能需要一种不同的机制。我不完全理解你需要从 Google 的 pub/sub 中得到什么,但是如果你只是想序列化访问一个一堆工作。

我很怀疑只要您的所有 I/O 都使用异步方法,您就会遇到 nodejs 事件循环阻塞问题。您正在做的任何事情听起来都不 CPU-繁重,这就是阻止事件循环的原因(长 运行 CPU-繁重的操作)。你的整个项目可能受到 MongoDB 和你用来发送电子邮件的任何东西的限制,所以你应该确保你不会压倒其中任何一个,以至于它们变得迟缓并失去吞吐量。

回答原问题:

  1. Should I be using a message queue to start this long-running job given that the message queue expects a response in 10 mins or is there some other architecture I should consider?

是的,消息队列很适合处理这类事件。重要的是要确保最后的动作是幂等的,这样即使你不小心处理了重复的事件,最后的结果也会应用一次。来自 Google Cloud 的 guide 是使订阅者幂等的有用资源。

为了绕过 Pub/Sub 的 10 分钟限制,我最终创建了一个内存中 table 来跟踪活动作业。如果作业正在处理中并且 Pub/Sub 再次发送消息,则它不会执行任何操作。如果服务器重新启动并丢失作业,内存中的 table 也会消失,因此如果作业不完整,可以再次处理。

  1. If multiple such jobs start, should I be worried about the Node JS event loop being blocked. Each job is basically iterating through a MongoDB cursor creating hundreds of thousands of emails. I have ignored this for now as per the comment left by jfriend00. You can also rate-limit the number of jobs being processed.