[英]nodejs HTTP server can't handle large response on high load
在高负载服务器上测试,每秒约500-600个请求。 经过几个小时的调试,我最终得到了一个简单的HTTP服务器。
我注意到当响应体变大时,让我们说,60k,我得到了这个错误:
(node) warning: possible EventEmitter memory leak detected. 11 listeners added. Use emitter.setMaxListeners() to increase limit.
Trace
at Socket.EventEmitter.addListener (events.js:160:15)
at Socket.Readable.on (_stream_readable.js:679:33)
at Socket.EventEmitter.once (events.js:179:8)
at TCP.onread (net.js:527:26)
之后,CPU变得疯狂了
但是,使用完全相同的代码,当响应设置为10k的文本时,一切都顺利进行。 奇怪的...
有没有人遇到过这个??? 请求帮助。
这是完整的脚本:
var
cluster = require('cluster'),
numCPUs = require('os').cpus().length;
if(cluster.isMaster){
for (var i = 0; i < numCPUs; i++) cluster.fork();
cluster.on("exit", function(worker, code, signal) {
cluster.fork();
});
}
else{
var http = require('http');
var app = function(req, res){
res.writeHead(200, {'Content-Type': 'text/html', 'Access-Control-Allow-Origin': '*'});
res.end( 60k_of_text___or___10k_of_text );
};
http.createServer(app).listen(80);
}
现在所有字符串首先转换为Buffer实例。 这可能会在每次请求后对垃圾收集器进行大量加载以进行清理。 使用--prof
运行应用程序并使用tools/*-tick-processor
检查v8.log
文件,您可能会看到。
正在进行纠正此操作的工作,以便将字符串直接写入内存,然后在请求完成时进行清理。 它已经在f5e13ae中实现了文件系统写入,但还没有用于其他情况(实现起来比听起来要困难得多)。
将字符串转换为缓冲区也非常昂贵。 特别是对于utf8
字符串(默认情况下)。 你可以在哪里,绝对预先将字符串缓存为缓冲区并使用它。 这是一个示例脚本:
var http = require('http');
var str = 'a';
for (var i = 0; i < 60000; i++)
str += 'a';
//str = new Buffer(str, 'binary');
http.createServer(function(req, res) {
res.writeHead(200, {'Content-Type': 'text/plain',
'Access-Control-Allow-Origin': '*'});
res.end(str);
}).listen(8011, '127.0.0.1');
以下是运行wrk 'http://127.0.0.1:8011/'
对服务器首先将str
作为字符串传递,然后作为持久缓冲区的结果:
Running 10s test @ http://127.0.0.1:8011/
2 threads and 10 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 0.00us 0.00us 0.00us -nan%
Req/Sec 0.00 0.00 0.00 -nan%
8625 requests in 10.00s, 495.01MB read
Requests/sec: 862.44
Transfer/sec: 49.50MB
Running 10s test @ http://127.0.0.1:8011/
2 threads and 10 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 624.07us 100.77us 4.45ms 99.17%
Req/Sec 7.98k 729.82 9.00k 57.59%
158711 requests in 10.00s, 8.90GB read
Requests/sec: 15871.44
Transfer/sec: 0.89GB
至少如果你知道你的传递只包含ascii字符的字符串,那么用res.end(str)
替换res.end(str)
res.end(new Buffer(str, 'binary'))
。 这将使用更快的v8::String::WriteOneByte
方法。 以下是使用该更改的结果:
Running 10s test @ http://127.0.0.1:8011/
2 threads and 10 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 827.55us 540.57us 7.03ms 97.38%
Req/Sec 6.06k 1.11k 8.00k 85.93%
121425 requests in 10.00s, 6.81GB read
Requests/sec: 12142.62
Transfer/sec: 696.89MB
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.