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

问题描述

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

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

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

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

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

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

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

解决方法

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

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

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

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

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

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

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

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

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

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


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