我运行以下非常简单的代码:创建一个监听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)
答案 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 somaxconn
和sysctl
更新为更大的数字,并在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。(我找不到在何处重置backlog
在http
模块中,这让我很困扰。有人可以解释吗?谢谢)
现在错误没有显示。