NodeJS-是否可以有两个单独的集群?

时间:2019-02-18 18:47:45

标签: javascript node.js multithreading cluster-computing global

TL; DR

是否可能有两个不同的群集主服务器不是共享的全局主机?例如创建新实例myCluster = new cluster()

更长的版本

在NodeJS中使用新的集群模块一段时间后,我遇到了两个单独的集群重叠的问题。不管您从何处require集群模块在当前运行的进程中都是全局的,两个不同的库(npm软件包)可以访问同一集群主服务器。

  

从任何库调用cluster.workers将列出每个库产生的每个工作程序。

每个人都在疯狂地讨论它的简单性和效率,但是遇到两个使用同一集群的库的问题后,我担心一个会通过使用某些全局集群来干扰另一个函数,例如cluster.disconnect(),或访问全局工作程序对象cluster.workers。我知道这是一个相当单一的用例模块,“创建一个可自我维持的一次性工作者集群,可以通过看门狗轻松地重新启动它。”

但这是多线程任务最简单的解决方案,child_process使很多麻烦事倍受困扰。如果两个图书馆认为有必要使用cluster,却没有努力跟踪哪些工人属于他们,而是称其为厚脸皮

,该怎么办?
Object.values(cluster.workers).forEach(worker => worker.kill())

作为他们的清理工作?

集群是否可以有两个不同的“实例”或“命名空间” ,以免干扰任何其他集群主服务器?还是集群模块只是您必须接受的全局变量?

我已经深入研究了文档,但是据我所知,无法通过调用myCluster = new cluster()或将某些唯一的标识传递给派生的工人来创建新的集群实例。我感到惊讶的是,没有明显的解决方案可以解决此问题,尤其是考虑到它针对的是不应该存在此类问题的企业应用程序。

编程的趋势(并且已经有一段时间了)是远离全局实例,并创建仅了解它们需要知道的所谓的“哑组件”的自足实例。集群是NodeJS的一个相当新的功能,他们是否决定半实施一项重要功能?

对于您对此问题的想法或解决方法,我将不胜感激。现在,我正在创建一个可以从任务分配中大大受益的库,但是我不想弄脏依赖于程序包的全局群集。我应该使用低级child_process吗?

非常感谢!

2 个答案:

答案 0 :(得分:1)

回答我自己的问题

切换到较低级别的child_process模块后,出于一个简单的原因,我恢复了回到使用cluster的状态。 Node.js的--inspect调试器。

在调试另一个程序包很费劲之后,我将错误追溯到一个依赖关系,该依赖关系是我自己的实现child_process方法的库。它是使用从父进程继承的child-process分叉的execArgs,这意味着child_process试图与父进程绑定到 same 检查器端口,静默失败并崩溃。

虽然我的第一个解决方法是为child_process生成一个随机的免费(由OS分配)调试端口,但这是一个有效的解决方法,但是却带来了自己的问题。最重要的是,该过程必须通过每次复制唯一端口来手动附加到调试器。

VS Code具有神奇的autoAttachChildProcesses,它可以发现分叉的进程,但仅在使用cluster 时才发现,至少就我而言。似乎cluster在派生过程中有一些涂糖,使其在调试过程中更易于发现和适应,或者VS Code仅侦听cluster.fork()。我屈服于使我的工作人员对整个应用程序可见的缺点,而希望为用户提供更可靠的体验。

这是令人讨厌的行为,在GitHub上存在未解决的问题:https://github.com/nodejs/node/issues/9435


我的结论是,集群模块可提供更统一的分叉体验以及更智能的流程处理和发现,而程序包则必须尊重从不接触cluster.workers或类似的全局功能,而应保持由cluster.fork()返回的自己的工人数组。

答案 1 :(得分:0)

没有是的。

请参见,因为用节点术语进行集群意味着对当前进程进行分叉,所以实际上没有集群-只是forks列表= worker。

但是:您可以派生并要求您想要将派生作为工作程序的脚本(或if-else放入一个块中),然后将该新工作程序保存到自己的数组= cluster / fork_list中。

我有一个简单的支持模块,用于分隔工作程序脚本(并仅加载不同的脚本+处理通信):runworker