【问题标题】:Managing multiple long-running tasks concurrently in JS (Node.js)在 JS (Node.js) 中同时管理多个长时间运行的任务
【发布时间】:2021-02-27 02:48:11
【问题描述】:

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

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

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

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

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

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

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

【问题讨论】:

    标签: javascript node.js multithreading node-worker-threads


    【解决方案1】:

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

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

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

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

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

    在 Go 中,我可以为我的无尽任务生成一个 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 来处理它们。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-10-15
      • 1970-01-01
      • 2013-01-12
      • 2012-04-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多