mur*_*lai 9 http request load-testing node.js
这是我的示例代码:
var http = require('http');
var options1 = {
host: 'www.google.com',
port: 80,
path: '/',
method: 'GET'
};
http.createServer(function (req, res) {
var start = new Date();
var myCounter = req.query['myCounter'] || 0;
var isSent = false;
http.request(options1, function(response) {
response.setEncoding('utf8');
response.on('data', function (chunk) {
var end = new Date();
console.log(myCounter + ' BODY: ' + chunk + " time: " + (end-start) + " Request start time: " + start.getTime());
if (! isSent) {
isSent = true;
res.writeHead(200, {'Content-Type': 'application/xml'});
res.end(chunk);
}
});
}).end();
}).listen(3013);
console.log('Server running at port 3013');
Run Code Online (Sandbox Code Playgroud)
我发现,如果我连接到其他服务器(谷歌或任何其他),响应将变得越来越慢,几秒钟.如果我连接到同一网络中的另一个node.js服务器,则不会发生这种情况.
我用JMeter来测试.每秒50个并发,1000个循环.
我不知道问题是什么......
=========================
进一步的调查:
我在Rackspace上运行相同的脚本,也在EC2上运行以进行测试.该脚本将使用http.request连接到:Google,Facebook,以及我的另一个脚本,它只是输出由另一个EC2实例托管的数据(如hello world).
测试工具我就是桌面上的jMeter.
pre-node.js test:jMeter - > Google Result:快速且一致.jMeter - > Facebook结果:快速且一致.jMeter - >我的简单输出脚本结果:快速且一致.
然后我用100个循环制作50个Concurrent Threads/sec,测试我的Rackspace nodejs,然后测试具有相同性能问题王的EC2 node.js jMeter - > node.js - > Google Result:从50 ms开始在200个重新设定中2000毫秒.
jMeter - > node.js - > Facebook结果:200个重新设置后,从200毫秒到3000毫秒.
jMeter - > node.js - >我的简单输出脚本结果:从100 ms开始,在200次重新设置之后转换为1000 ms.
前10-20个请求很快,然后开始减速.
然后,当我更改为10个并发线程时,事情开始发生变化.响应非常一致,没有减速.
与Node.js(http.request)可以处理的并发线程数有关.
------------ 更多 --------------
我今天做了更多测试,这里是:我使用了http.Agent并增加了最大套接字.然而,有趣的是,在一个测试服务器(EC2)上,它改进了很多而且没有更慢.HOwever,另一台服务器(rackspace)只有一点点改进.它仍显示减速.我甚至在请求标题中设置了"Connection:close",它只提高了100ms.
如果http.request正在使用连接池,如何增加它?
在两个服务器中,如果我执行"ulimit -a",则打开的文件数为1024.
-------------**更多更多**-------------------
似乎即使我将maxSockets设置为更高的数字,它只能在某种限制下工作.似乎存在内部或OS依赖的套接字限制.然而要提高它?
-------------**广泛测试后**---------------
看了很多帖子后,我发现:
引用自:https://github.com/joyent/node/issues/877
1)如果我用connection ='keep-alive'设置标题,性能很好,可以达到maxSocket = 1024(这是我的linux设置).
var options1 = {
host: 'www.google.com',
port: 80,
path: '/',
method: 'GET',
**headers: {
'Connection':'keep-alive'
}**
};
Run Code Online (Sandbox Code Playgroud)
如果我将其设置为"连接":"关闭",则响应时间将慢100倍.
有趣的事发生在这里:
1)在EC2中,当我第一次使用Connection进行测试时:保持活动状态,大约需要20-30 ms.然后,如果我更改为Connection:Close或设置Agent:false,响应时间将减慢到300 ms.WIHTOUT重新启动服务器,如果我再次切换到Connection:keep-alive,响应时间将进一步减慢到4000ms.要么我必须重新启动服务器或等待一段时间才能恢复20-30ms的照明速度响应.
2)如果我用agent运行它:false,首先,响应时间将减慢到300ms.但是,它会再次变得更快并恢复到"正常"状态.
我的猜测是连接池仍然有效,即使你设置agent:false.但是,如果你保持连接:keep-alive,那么肯定会很快.只是不要切换它.
2011年7月25日更新
我尝试了最新的node.js V0.4.9以及来自https://github.com/mikeal/node/tree/http2的http.js和https.js修复程序
性能更好,更稳定.
我解决了这个问题
require('http').globalAgent.maxSockets = 100000
Run Code Online (Sandbox Code Playgroud)
要么
agent = new http.Agent()
agent.maxSockets = 1000000 # 1 million
http.request({agent:agent})
Run Code Online (Sandbox Code Playgroud)
这不一定能解决您的问题,但它会稍微清理您的代码并以您应该的方式利用各种事件:
var http = require('http');
var options1 = {
host: 'www.google.com',
port: 80,
path: '/',
method: 'GET'
};
http.createServer(function (req, res) {
var start = new Date();
var myCounter = req.query['myCounter'] || 0;
http.request(options1, function(response) {
res.on('drain', function () { // when output stream's buffer drained
response.resume(); // continue to receive from input stream
});
response.setEncoding('utf8');
res.writeHead(response.statusCode, {'Content-Type': 'application/xml'});
response.on('data', function (chunk) {
if (!res.write(chunk)) { // if write failed, the stream is choking
response.pause(); // tell the incoming stream to wait until output stream drained
}
}).on('end', function () {
var end = new Date();
console.log(myCounter + ' time: ' + (end-start) + " Request start time: " + start.getTime());
res.end();
});
}).end();
}).listen(3013);
console.log('Server running at port 3013');
Run Code Online (Sandbox Code Playgroud)
我去掉了身体的输出。由于我们从一个套接字流式传输到另一个套接字,因此我们无法确保在不缓冲的情况下随时看到整个主体。
编辑:我相信节点正在使用连接池进行http.request。如果您有 50 个并发连接(因此有 50 个并发 http.request 尝试),您可能会遇到连接池限制。我目前没有时间为您查找此内容,但您应该查看有关 http 的节点文档,尤其是 http 代理。
编辑 2: node.js 邮件列表上有一个关于非常相似问题的线程。你应该看看它,尤其是 Mikael 的帖子应该很有趣。agent: false他建议通过将该选项传递给调用来完全关闭请求的连接池http.request。我没有任何进一步的线索,所以如果这没有帮助,也许您应该尝试在 node.js 邮件列表上获取帮助。