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

标签 javascript node.js sockets phantomjs

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

例如,采用以下代码,它在自己的端口上创建 5 个 http.Server,然后关闭除最后一个(第 5 个)之外的所有服务器。

'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 模块在 workers 中运行相同的代码:

'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 的端口,即使它们已经关闭:

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)

我的问题很简单:为什么?以及如何让他们关闭?我怀疑如果我在 net.Server.listen() 中使用 exclusive 选项端口可能会关闭,但是 http.Server.listen() API 似乎没有将此选项散列作为参数。

这个问题的起源是在使用集群模块的 Express.js 应用程序中使用 phantom-node(与 phantomjs)随着时间的推移打开许多页面时出现的问题。为了确保在创建新的幻影 Node 实例时没有端口冲突,并避免 EADDRINUSE,我进行了端口扫描并检查我将要使用的端口是否可用。问题是,随着时间的推移,越来越多的端口被打开,并且由于它们从未关闭, Node 最终会因 EMFILE 错误而崩溃。

最佳答案

似乎,所描述的问题出现在 Node v0.11.1 之前。从 0.11.2 开始,套接字在关闭时成功取消链接。由 this commit 修复.

很酷。

关于javascript - Node.js 集群模块不会在 http.Server.close() 上释放套接字/端口,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29005065/

相关文章:

c++ - 自动检测 TCP 连接是否使用 SSL/TLS?

javascript - 使用 jsonp 通过 HTTPS 发送密码是否安全

javascript - 获取声音节奏 - javascript

Javascript 在 Chrome 扩展中打开多个选项卡

node.js - 上传到 Stripe.fileUploads 时使用 URL 文件

javascript - 当嵌套的 promise 实际上有数千个时,这是一个正确的异步/等待实现吗?

node.js - 防止脚本模板的 Jade 插值

swift - 套接字阻塞 UI 的挑战(我相信是这样)

javascript - requirejs - 在非 SPA 站点中的使用

sockets - Easy Button to UDP 数据包 - 控制板术语