node-interview [IV] : Child process & Cluster

本文详细介绍了Node.js中子进程的创建,特别是`fork`方法和IPC通信机制,以及`Cluster`模块的工作原理和调度策略。子进程通过`child_process.fork()`创建,并使用Unix Domain Socket进行高效通信。集群模块基于`child_process.fork()`,采用轮询策略分配连接到工作进程,确保负载均衡。文章还深入解析了监听端口的并发处理,避免了惊群效应,强调了父子进程间通信的重要性。
摘要由CSDN通过智能技术生成

Child process

一些基础性的介绍在这里child_process有两个核心方法,spawnfork,二者唯一的区别是后者会在创立子进程的同时建立一个IPC通道,因此就分析fork好了。本文将只讨论unix下的实现。

fork

unix下有一个fork函数可以用来创建子进程。文档里有这么一句话:

Note: Unlike the fork(2) POSIX system call, child_process.fork() does not clone the current process.

这句话给人一种child_process和unix的fork没关系的错觉,像是libuv自己实现了一套fork方法一样。实际上,child_process.fork最终调用的就是libuv里的deps/uv/src/unix/process.c: uv_spawn(),最终还是调用了系统的fork. 而文档里说的没有克隆原始进程,意思应该是copy-on-write机制。

IPC channel

IPC在unix下有很多种实现方式,node使用的是unix domain socket方案。相较针对网络通讯设计的socket,效率更高。

unix下创建unix domain socket的系统函数是socketpair,它将返回一对文件描述符fd[0] fd[1]。对其中任意一个执行写操作之后,对这个文件描述符的读取操作会阻塞,只可以在另一个上读出数据。它实际上是一个全双工的IPC。而使用管道的话是单工的,双工通信需要创建两次,比较繁琐。

node在调用fork操作的时候,会通过环境变量NODE_CHANNEL_FD传递给子进程一个值作为IPC频道的暗号。我之前有参考过CNODE论坛上的帖子,看完这个帖子我有一个最大的疑问:fork操作后,子进程是会完整的继承原始父进程打开的文件描述符的,所以如果在fork之前调用了socketpair,子进程是有这个文件描述符的,又何必要用NODE_CHANNEL_FD折腾一大圈呢?

child_process.fork最终调用的是libuv里的uv_spawn, 来仔细分析一下uv_spawn这个函数吧。第一个关键函数是uv__process_init_stdio,它内部调用了uv__make_socketpair,而该函数又调用了系统层面的socketpair生成一对fd,这里没什么疑问。在生成socketpair后,有这样一段代码:

if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds))
    return -errno;
uv__cloexec(fds[0], 1);
uv__cloexec(fds[1], 1);

这个uv__cloexec将新生成的两个fd配置为exec调用后即关闭,即close on exec. 这里是

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值