在 JS (Node.js) 中同时管理多个长时间运行的任务

Gil*_*mes 5 javascript multithreading node.js node-worker-threads

这里是 Golang 开发人员,正在尝试学习 JS (Node.js)。

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

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

我怎样才能在JS中实现这样的东西?我浏览了 Node.js API 文档,发现了一些有趣的事情:

  • 集群:似乎并不完全是我正在寻找的
  • 子进程:可以工作,但我会为每个客户端/用户生成 1 个进程,我认为开销会很大
  • Worker 线程:更像是这样,但文档指出它们“对于执行 CPU 密集型 JavaScript 操作非常有用”并且“Node.js 内置异步 I/O 操作比 Workers 更高效”

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

任何意见或建议将不胜感激。谢谢!

jfr*_*d00 1

现在想象一下,我想创建某种可以运行无尽任务的服务,例如,它可以是一个从 websocket 接收数据并保持内部状态更新的函数

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

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

现在,我希望能够同时为多个用户提供服务,并且每个用户也可以在某个时刻停止其特定的正在进行的任务。

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

在Go中,我可以为我的endlessTask生成一个goroutine,在请求调度程序中存储某种会话来跟踪每个任务所属的用户。

我不知道 goroutine,但有很多用于存储用户状态的选项。如果这只是您在已经拥有 webSocket 时需要能够访问的信息,并且不需要它持续存在,那么您可以将状态直接添加到 webSocket 对象中。该对象将在您收到 webSocket 事件时可用,因此您始终可以将其放在那里,以便在有传入数据时进行更新。您还可以将状态放在其他位置(数据库、通过套接字索引的映射对象或通过用户名或您需要能够查找的任何内容索引的映射对象) - 这实际上取决于状态到底是什么。

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

您所描述的内容听起来不像需要集群、子进程或工作线程的任何内容,除非您对数据执行的操作是 CPU 密集型的。只需对每个 webSocket 上的传入数据使用事件侦听器,就可以让 Nodejs 非常高效的异步 I/O 处理发挥作用。这是它最擅长的事情之一。

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


当您的 Javascript 中用于处理传入数据的 CPU 处理量超过单个内核可以处理的量时,您就会涉及集群、子进程或工作线程。只有当您证明您的 Nodejs 服务器中的 CPU 使用存在可扩展性问题时,我才会去那里。然后,您希望采用一种仅添加一些其他进程或线程来共享负载(而不是每个连接一个)的架构。如果您有特定的 CPU 密集型进程(自定义加密或压缩是典型的示例),那么您可能会帮助创建一些其他进程或工作线程,它们仅处理 CPU 密集型工作的工作队列。或者,如果只是增加可用于处理传入数据的总体 CPU 周期,那么您可能会进行集群,让每个传入的 webSocket 分配到一个集群,并且仍然使用前面描述的相同事件处理逻辑,但现在您拥有了 webSocket分成多个进程,以便您有更多的 CPU 来处理它们。