Node.js集群模块不释放http.Server.close()上的套接字/端口

在Node.js脚本中,我试图打开一些端口/套接字,然后再closures它们。 使用Node.js集群模块时遇到麻烦。 它似乎没有以不使用群集模块时相同的代码相同的方式closures端口。

例如,下面的代码创build5个http.Server,每个都在它自己的端口上,然后closures除最后一个(第五个)之外的所有其他端口。

'use strict'; var http = require('http'); function goGoGadget(i) { console.log('var i = ', i); var httpServer = http.createServer(); var nextPort = 4000 + i; console.log('about to listen on port', nextPort); httpServer.listen(nextPort); if (i < 5) { httpServer.on('listening', function() { console.log('closing port:', nextPort); httpServer.close(function() { console.log('closed server on port:', nextPort); }); }); } } goGoGadget(1); goGoGadget(2); goGoGadget(3); goGoGadget(4); goGoGadget(5); 

正如所料,只有一个端口仍然由node.js打开:

 dhcp50:test marco$ lsof -i -n -P | grep node node 20895 marco 16u IPv4 0xb242422d2e0e2bb1 0t0 TCP *:4005 (LISTEN) 

然后,使用相同的代码,但在使用Cluster模块的工人中运行:

 'use strict'; var cluster = require('cluster'); var http = require('http'); function goGoGadget(i) { console.log('var i = ', i); var httpServer = http.createServer(); var nextPort = 4000 + i; console.log('about to listen on port', nextPort); httpServer.listen(nextPort); if (i < 5) { httpServer.on('listening', function() { console.log('closing port:', nextPort); httpServer.close(function() { console.log('closed server on port:', nextPort); }); }); } } if (cluster.isMaster) { var numWorkers = 5; for (var i = 0; i < numWorkers; i += 1) { console.log ('forking ', i + 1); cluster.fork(); } } else { goGoGadget(cluster.worker.id); } 

这一次,Node.js一直保留在前4个http.Server的端口上,尽pipe它们已经closures了:

 dhcp50:test marco$ lsof -i -n -P | grep node node 20900 marco 17u IPv4 0xb242422d2d9682e1 0t0 TCP *:4004 (LISTEN) node 20900 marco 18u IPv4 0xb242422d2d5faa11 0t0 TCP *:4001 (LISTEN) node 20900 marco 19u IPv4 0xb242422d2d5fd621 0t0 TCP *:4005 (LISTEN) node 20900 marco 20u IPv4 0xb242422d2d985141 0t0 TCP *:4002 (LISTEN) node 20900 marco 21u IPv4 0xb242422d2d9862e1 0t0 TCP *:4003 (LISTEN) node 20905 marco 13u IPv4 0xb242422d2d5fd621 0t0 TCP *:4005 (LISTEN) 

我的问题很简单:为什么? 如何让他们closures? 我有一个怀疑,如果我使用net.Server.listen()中的排他选项的端口可能会closures,但http.Server.listen() API似乎并没有把这个选项散列作为参数。

这个问题的起源来自使用幻像节点(带有phantomjs)在使用群集模块的Express.js应用程序中随着时间的推移打开许多页面的问题。 为了确保创build一个新的幻影节点实例时没有端口冲突,为了避免EADDRINUSE ,我做了端口扫描,并检查我即将使用的端口是否可用。 问题变成了,随着时间的推移,越来越多的端口被打开,并且因为它们从不closures,所以节点最终会因EMFILE错误而崩溃。

看来,所描述的问题通过节点v0.11.1出现。 从0.11.2socketsclosures时,成功解除了链接。 通过这个提交修复。

凉。

我注意到的可能是你的答案的一部分:有时系统在被要求closures时不会释放端口。 我有一个closures的小shell脚本(nodejs持久性模块)的问题,从git拉新的代码,并再次启动它。 服务器不会再启动,因为它说“端口xxxx已经在使用”。