工作原理

工作进程是使用 child_process.fork() 方法进行衍生的,以便它们可以通过 IPC 与父进程进行通信并通过服务器来处理来回。

集群模块支持两种分发传入连接的方法。

第一种(除 Windows 外,所有平台上的默认方法)为轮询式:主进程监听一个端口,接受新连接,并以轮询的方式分发给工作进程,并用一些内建机制来避免单个工作进程超载。

第二种方式是,主进程建立监听 socket,并将它发送给感兴趣的工作进程,由工作进程直接接受传入的连接。

第二种方式理论上性能最佳。然而在实践中,由于操作系统的调度变幻莫测,分发往往十分不平衡。负载曾被观测到超过 70% 的连接只结束了八个进程中的两个。

因为 server.listen() 将大部分工作交给了主进程,所以一个普通的 Node.js 进程和一个集群工作进程会在三种情况下有所区别:

  1. server.listen({fd: 7}) 由于消息被传递到主进程,父进程中的文件描述符 7 会被监听,并且句柄会被传递给工作进程,而不是监听工作进程中文件描述符 7 所引用的东西。

  2. server.listen(handle) 明确地监听一个句柄会使得工作进程使用所给句柄,而不是与主进程通讯。如果工作进程已经拥有了该句柄,则假定你知道你在做什么。

  3. server.listen(0) 通常,这会让服务器监听一个随机端口。然而,在集群中,各个工作进程每次 listen(0) 都会得到一样的“随机”端口。实际上,端口在第一次时是随机的,但在那之后却是可预知的。如果你想要监听一个唯一的端口,则请根据集群工作进程 ID 来生成端口号。

由于在 Node.js 或你的程序中并没有路由逻辑,工作进程之间也没有共享的状态,因此在你的程序中,诸如会话和登录等功能应当被设计成不能太过依赖于内存中的数据对象。

由于工作进程都是独立的进程,因此它们会根据你的程序的需要被终止或重新衍生,并且不会影响到其它工作进程。只要还有工作进程存在,服务器就会继续接受连接。但是,Node.js 不会自动为你管理工作进程的数量,根据你的程序所需管理工作进程池是你的责任。