Node.js Http.request在负载testing下变慢。 难道我做错了什么?

这是我的示例代码:

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'); 

我发现,如果我连接到其他服务器,(谷歌或任何其他),响应会变得越来越慢,几秒钟。 如果我连接到同一networking中的另一个node.js服务器,则不会发生这种情况。

我使用JMeter来testing。 1000个循环每秒50个并发。

我不知道问题是什么

=========================

进一步的调查:

我在Rackspace上运行相同的脚本,并在EC2上运行testing。 脚本将使用http.request连接到:Google,Facebook,以及我的另一个脚本,它只是输出数据(如hello world),由另一个EC2实例托pipe。

testing工具我只是在桌面上的jMeter。

pre-node.jstesting:jMeter – > Google结果:快速和一致。 jMeter – > Facebook的结果:快速和一致。 jMeter – >我的简单输出脚本结果:快速和一致。

然后我做了50个并行线程/秒,用100个循环,testing我的Rackspace nodejs,然后EC2 node.js,它具有相同的性能问题jMeter – > node.js – > Google结果:从50 ms到在200个需求中为2000毫秒。
jMeter – > node.js – > Facebook结果:从200 ms到200 ms之后需要3000 ms。
jMeter – > node.js – >我的简单输出脚本结果:在200个请求之后,从100 ms到1000 ms。
前10-20个请求很快,然后开始放慢速度。

然后,当我更改为10个并发线程时,事情开始发生变化。响应非常一致,不会减慢。

与Node.js(http.request)可以处理的并发线程数量有关。

———— 更多 ————–

我今天做了更多的testing,这里是:我使用http.Agent和增加最大套接字。 然而,有趣的是,在一个testing服务器(EC2)上,它提高了很多,并且没有减慢速度。 HOwever,其他服务器(机架空间)只有一点改进。 它仍然显示减速。 我甚至在请求头中设置了“Connection:close”,它只提高了100ms。

如果http.request正在使用连接池,如何增加它?

在这两个服务器上,如果我做“ulimit -a”,打开的文件的编号是1024。

————- ** 更多和更多 ** ——————-

看来,即使我把maxSockets设置为更高的数字,它只能在一些限制。 似乎有一个内部或操作系统依赖的套接字限制。 但是要碰到它?

————- **广泛的testing** —————

阅读了很多post后,我发现:



引自: https : //github.com/joyent/node/issues/877


1)如果我设置连接='保持活着'的头,性能是好的,可以上升到maxSocket = 1024(这是我的Linux设置)。

 var options1 = { host: 'www.google.com', port: 80, path: '/', method: 'GET', **headers: { 'Connection':'keep-alive' }** }; 

如果将其设置为“连接”:“closures”,则响应时间将会慢100倍。

有趣的事发生在这里:

1)在EC2中,当我第一次使用Connection:keep-alive进行testing时,大约需要20-30毫秒。 然后,如果我更改为连接:closures或设置代理:false,响应时间将减慢到300毫秒。 WIHTOUT重新启动服务器,如果我改变为Connection:keep-alive,响应时间会进一步减慢到4000ms。 要么我必须重新启动服务器或等待一段时间,以获得我的20-30ms的照明速度响应。

2)如果我用代理运行它:false,首先,响应时间将减慢到300ms。 但是,它会再次变得更快,回到“正常”。

我的猜测是连接池仍然有效,即使你设置代理:false。 但是,如果你保持连接:保持活跃,那么肯定会很快。 只是不要切换它。




2011年7月25日更新

我尝试了https://github.com/mikeal/node/tree/http2中最新的node.js V0.4.9和http.js&https.js修复

性能更好,更稳定。

我解决了这个问题

 require('http').globalAgent.maxSockets = 100000 

要么

 agent = new http.Agent() agent.maxSockets = 1000000 # 1 million http.request({agent:agent}) 

这不会不可避免地解决你的问题,但它会清理你的代码,并以你应该的方式使用各种事件:

 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'); 

我删除了身体的输出。 由于我们是从一个套接字stream到另一个套接字,所以我们不能确定在任何时候都看不到整个身体。

编辑:我相信节点使用连接池为http.request。 如果有50个并发连接(因此有50个并发的http.request尝试),则可能正在运行到连接池限制。 我目前没有时间为您查找,但是您应该查看关于http的节点文档,特别是http代理。

编辑2:有关于node.js邮件列表上非常类似的问题的线程 。 你应该看看它,特别是Mikael的post应该是有趣的。 他build议通过将选项agent: false传递给http.request调用来完全closures连接池。 我没有任何进一步的线索,所以如果这没有帮助,也许你应该尝试在node.js邮件列表上获得帮助。

Github问题877可能是相关的:

https://github.com/joyent/node/issues/877

虽然我不清楚这是你打的。 当我点击时,“agent:false”解决方法为我工作,就像在请求中设置“connection:keep-alive”标题一样。

我正在同样的问题挣扎。 我发现我的瓶颈是DNS的东西,虽然我不清楚在哪里/为什么。 如果我向http://myserver.com/asd发送请求,我几乎无法运行50-100 rq / s,如果超出100 rq / s,并且有更多的东西变成灾难,响应时间变得很大,请求永远不会完成,并无限期地等待,我需要杀死-9我的服务器。 如果我向服务器的IP地址发送请求,一切都稳定在500 rq / s,虽然不完全平滑,并且graphics(我有实时graphics)是高峰的。 请注意,Linux中打开文件的数量还是有限制的,我设法打了一次。 另一个观察结果是单节点过程不能平稳地达到500 rq / s。 但是我可以启动4个节点进程,每个节点进程达到200 rq / s,并且获得非常平滑的graphics和一致的CPU /净负载以及非常短的响应时间。 这是节点0.10.22。