Node.js中child_process.fork的事件监听器是否会在内存中持久化?
Node.js fork子进程事件监听器的内存疑问解答
首先直接给你结论:不会留存100个事件监听器,也不会出现内存中堆积监听器的情况,原因如下:
每个请求对应独立的子进程实例
当用户访问/compute路径时,你的代码会通过fork('compute.js')创建一个全新的ChildProcess实例(也就是代码里的compute变量)。这个变量属于请求处理函数的局部作用域——每个请求进来都会生成完全独立的实例,彼此之间没有关联。
监听器会随子进程实例被GC回收
当子进程完成计算并发送sum消息后,父进程调用res.end()完成响应。此时,该请求的处理函数执行上下文结束,compute变量失去了所有引用(没有全局变量或其他持久化引用持有它)。Node.js的垃圾回收器会识别到这个ChildProcess实例不再被使用,进而回收它,绑定在它身上的message事件监听器也会被一并清理掉。
补充:子进程的存活优化点
这里要提个细节:原示例里的子进程在发送完消息后并不会自动退出,会一直占用系统资源。如果服务处理大量请求,会导致很多闲置子进程堆积。建议在子进程发送完结果后主动退出,或者在父进程收到消息后终止子进程:
方式1:在子进程中主动退出
修改compute.js:
const longComputation = () => { let sum = 0; for (let i = 0; i < 1e9; i++) { sum += i; }; return sum; }; process.on('message', (msg) => { const sum = longComputation(); process.send(sum); process.exit(); // 发送结果后立即退出子进程 });
方式2:在父进程中终止子进程
修改server.js的消息监听器:
compute.on('message', sum => { res.end(`Sum is ${sum}`); compute.kill(); // 收到结果后终止子进程 });
这样不仅能节省系统资源,也能让父进程里的ChildProcess实例更快被垃圾回收。
总结
处理100个请求时,会创建100个独立的子进程和对应的100个监听器,但每个请求完成后,对应的子进程(如果做了退出处理)和监听器都会被清理,不会在内存中堆积100个活跃的监听器。
内容的提问来源于stack exchange,提问作者Cazineer
相关产品推荐
相关产品推荐

