在 JS (Node.js) 中同时管理多个 long-运行 任务

Managing multiple long-running tasks concurrently in JS (Node.js)

这里是Golang开发者,正在努力学习JS(Node.js)。

我习惯在 Go 中使用 goroutines,为了简单起见,我们假设它们只是线程(实际上它们不完全是线程,更像是 Green Threads,但请耐心等待!) .

想象一下,现在我想创建某种服务,可以 运行 一些 endlessTask 例如,可以是从 websocket 接收数据并保持内部状态更新的函数,以后可以查询。现在,我希望能够同时为多个用户提供服务,并且他们每个人也可以在某个时候停止他们正在进行的特定任务。在 Go 中,我可以为我的 endlessTask 生成一个 goroutine,在请求调度程序中存储某种会话以跟踪每个任务属于哪个用户。

如何在 JS 中实现这样的功能?我查看了 Node.js API 文档,发现了一些有趣的东西:

我不确定在没有多线程或多处理的情况下如何处理这种情况。在这种情况下,工作线程解决方案是否可行?

如有任何意见或建议,我们将不胜感激。谢谢!

Imagine now that I want to create some kind of service that can run some endlessTask which, for example, could be a function that receives data from a websocket and keeps an internal state updated

因此,您需要考虑事件和事件处理程序而不是线程,因为这是 nodejs 架构的核心,尤其是 I/O。因此,如果您希望能够读取传入的 webSocket 数据并在数据到达时更新某些内部状态,您所做的就是为传入的 webSocket 数据设置一个事件处理程序。每当有数据等待读取并且解释器返回事件循环时,该事件处理程序就会被调用。

您不必为此创建任何线程结构或任何类型的循环或类似的东西。只需添加正确的事件处理程序,让它在有可用传入数据时调用您。

Now, I want to be able to serve multiple users at the same time and each of them can also stop their specific ongoing task at some point.

只需为每个 webSocket 添加一个事件侦听器,您的 nodejs 服务器就可以轻松地为多个用户提供服务。当用户断开他们的 webSocket 时,侦听器会自动消失。在这方面没有其他事情要做或清理,除非你想更新内部状态,在这种情况下你也可以监听 disconnect 事件。

In Go, I could just spawn a goroutine for my endlessTask, store some kind of session in the request dispatcher to keep track to which user each task belongs.

我不知道 goroutines,但是有很多用于存储用户状态的选项。如果它只是当您已经拥有 webSocket 并且不需要它持续存在时需要能够获得的信息,那么您可以直接将状态添加到 webSocket 对象。该对象将在您获得 webSocket 事件的任何时候可用,因此您可以始终将它放在那里以在有传入数据时进行更新。您还可以将状态放在其他地方(一个数据库,由套接字或用户名索引的 Map 对象,或者您需要能够查找它的任何内容) - 这实际上取决于状态到底是什么。

I'm not sure how I could handle this scenario without multi-threading or multi-processing. Would the worker threads solution be viable in this case?

您所描述的内容听起来不像任何需要集群、子进程或工作线程的东西,除非您对数据所做的事情是 CPU 密集型的。仅对每个 webSocket 上的传入数据使用事件侦听器将使 nodejs 非常高效和异步 I/O 处理开始发挥作用。这是它最擅长的事情之一。

请记住,nodejs 中的 I/O 可能与您所习惯的有点不同。您不会创建等待 webSocket 上传入数据的阻塞读取循环。相反,您只需为传入数据设置一个事件侦听器,它会在传入数据可用时调用您。


涉及集群、子进程或工作线程的时间是当您在 Javascript 中有更多的 CPU 处理来处理传入数据,而不是单个内核可以处理的时候。我只会去那里 if/when 你已经证明你的 nodejs 服务器中的 CPU 使用存在可伸缩性问题。然后,您想要追求一种架构,它只添加几个其他进程或线程来分担负载(而不是每个连接一个)。如果你有特定的 CPU 繁重的进程(自定义加密或压缩是典型的例子),那么你可能会帮助创建一些其他进程或工作线程来处理 CPU-heavy 的工作队列工作。或者,如果它只是增加了可用于处理传入数据的总体 CPU 周期,那么您可能会进入集群并让每个传入的 webSocket 分配给一个集群,并且仍然使用之前描述的相同事件处理逻辑,但现在您将 webSockets 拆分为多个进程,因此您可以 CPU 处理它们。