具有连接ECONNREFUSED的http.request

时间:2018-08-15 13:20:12

标签: node.js

我运行以下非常简单的代码:创建一个监听9900的服务器。然后等待1秒钟(以确保服务器已就绪),然后向该服务器发出1000个请求。我希望所有1000个请求都能正确完成。下面是我的代码:

const http = require('http');

// create server
http.createServer(function(req, res){
    res.end('ok')
}).listen(9900)

// issue 1000 requests after 1 second
setTimeout( async function(){
    for(let i=0;i<1000;i++) { // werid: it works well after changing 1000 to 800
        request();
    }
}, 1000 )

// actually I don't care if the Promise is resolved or rejected,
// so I don't await or chain then.
function request() {
    return new Promise((resolve, reject) => {
        const option = {
            protocol: 'http:',
            host: 'localhost',
            port: 9900,
            path: '/',
            agent: false,
            method: 'GET'
        };
        const req = http.request(option, function(res) {
            res.setEncoding('utf8');
            let body = '';
            res.on('data', (chunk) => {
                body += chunk;
            });
            res.on('end', () => {
                console.log(body)
                resolve(body)
            });
        });
        req.on('error', (e) => {
            console.error(`problem with request: ${e.message}`);
            console.log(e.stack)
            process.exit(1)
        });
        req.end();
    })
}

但是我收到ECONNREFUSED错误,这似乎机器无法建立更多的套接字。最糟糕的是,如果我将for loop更改为800,则不会显示错误。有潜在的原因或错误吗?谢谢。

problem with request: connect ECONNREFUSED 127.0.0.1:9900
Error: connect ECONNREFUSED 127.0.0.1:9900
    at Object._errnoException (util.js:1024:11)
    at _exceptionWithHostPort (util.js:1046:20)
    at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1182:14)

2 个答案:

答案 0 :(得分:1)

对于您为何尝试使用同一文件向服务器执行1000个请求,我没有任何背景。我的假设是您正在尝试进行某种压力测试。如果是这样,我强烈建议您为此使用正确的工具,例如Apache Benchmark。这是它的快速链接https://www.ndchost.com/wiki/apache/stress-testing-with-apache-benchmark

答案 1 :(得分:0)

经过很长一段时间,我终于明白了为什么会发生错误。在上面的演示测试中,我使用:

for(let i=0;i<1000;i++) { // werid: it works well after changing 1000 to 800
    request();
}

它发出了太多的tcp调用,超出了功能服务器无法在大约300毫秒内处理的能力(我在笔记本电脑上进行了测试)。

nodejs net模块在​​其backlog方法api中采用了server.listen()参数:

  

所有listen()方法都可以使用backlog参数来指定   挂起连接队列的最大长度。实际长度   将由操作系统通过sysctl设置确定,例如   Linux上的tcp_max_syn_backlog和somaxconn。这个的默认值   参数是511(不是512)。

根据以上来自nodejs文档的解释,我通过tcp_max_syn_backlog将Linux somaxconnsysctl更新为更大的数字,并在nodejs代码中增加了backlog

var content = 
`HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Content-Length: 10

{"code":0}`;

const server = net.createServer((socket) => {
    socket.end(content);
}).on('error', (err) => {
    console.log('err occurs', err);
    throw err;
}).listen(9900, 'localhost', 4000/*backlog*/)

请注意,我使用net.createServer而不是http.createServer来将backlog重置为4000。(我找不到在何处重置backloghttp模块中,这让我很困扰。有人可以解释吗?谢谢)

现在错误没有显示。