工作原理
【How it works】
工作进程是使用 child_process.fork() 方法生成的,这样它们就可以通过 IPC 与父进程通信,并来回传递服务器句柄。
【The worker processes are spawned using the child_process.fork() method,
so that they can communicate with the parent via IPC and pass server
handles back and forth.】
cluster 模块支持两种分发传入连接的方法。
【The cluster module supports two methods of distributing incoming connections.】
第一个(也是除了 Windows 外所有平台的默认方法)是轮询方式,其中主进程监听一个端口,接受新的连接,并以轮询的方式将它们分配给各个工作进程,同时内置了一些智能机制以避免某个工作进程过载。
【The first one (and the default one on all platforms except Windows) is the round-robin approach, where the primary process listens on a port, accepts new connections and distributes them across the workers in a round-robin fashion, with some built-in smarts to avoid overloading a worker process.】
第二种方法是主进程创建监听套接字并将其发送给有兴趣的工作进程。然后,工作进程直接接受传入的连接。
【The second approach is where the primary process creates the listen socket and sends it to interested workers. The workers then accept incoming connections directly.】
理论上,第二种方法应该能提供最佳性能。然而,在实际操作中,由于操作系统调度程序的差异,分布往往非常不平衡。有人观察到负载中,八个进程中超过70%的连接最终集中在其中两个进程上。
【The second approach should, in theory, give the best performance. In practice however, distribution tends to be very unbalanced due to operating system scheduler vagaries. Loads have been observed where over 70% of all connections ended up in just two processes, out of a total of eight.】
由于 server.listen() 将大部分工作交给主进程处理,有三种情况会导致普通 Node.js 进程与集群工作进程的行为不同:
【Because server.listen() hands off most of the work to the primary
process, there are three cases where the behavior between a normal
Node.js process and a cluster worker differs:】
server.listen({fd: 7})因为消息会传递给主进程,文件描述符 7 在父进程中 将会被监听,并且该句柄会传递给工作进程,而不是监听工作进程自己理解的数字 7 所引用的文件描述符。server.listen(handle)显式地监听句柄会使工作进程使用提供的句柄,而不是与主进程通信。server.listen(0)通常,这会导致服务器监听一个随机端口。但是,在集群环境中,每个工作进程每次执行listen(0)时都会收到相同的“随机”端口。实际上,端口第一次是随机的,但之后是可预测的。要监听唯一的端口,可以根据集群工作进程的 ID 生成端口号。
Node.js 不提供路由逻辑。因此,设计应用时要注意,不应过度依赖内存中的数据对象来处理会话和登录等功能。
【Node.js does not provide routing logic. It is therefore important to design an application such that it does not rely too heavily on in-memory data objects for things like sessions and login.】
因为工作进程都是独立的进程,所以它们可以根据程序的需求被终止或重新启动,而不会影响其他工作进程。只要还有一些工作进程存活,服务器就会继续接受连接。如果没有工作进程存活,现有的连接将被断开,新的连接将被拒绝。然而,Node.js 并不会自动管理工作进程的数量。应用有责任根据自身的需求来管理工作进程池。
【Because workers are all separate processes, they can be killed or re-spawned depending on a program's needs, without affecting other workers. As long as there are some workers still alive, the server will continue to accept connections. If no workers are alive, existing connections will be dropped and new connections will be refused. Node.js does not automatically manage the number of workers, however. It is the application's responsibility to manage the worker pool based on its own needs.】
尽管 node:cluster 模块的主要使用场景是网络,但它也可以用于其他需要工作进程的场景。
【Although a primary use case for the node:cluster module is networking, it can
also be used for other use cases requiring worker processes.】