以下是我的示例代码:
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');
我发现,如果我连接到其他服务器(谷歌或任何其他服务器),响应将变得越来越慢到几秒钟。如果我连接到同一网络中的另一个node.js服务器,则不会发生这种情况。
我使用JMeter进行测试。每秒50个并发,1000个循环。
我不知道问题是什么......
=========================
进一步调查:
我在Rackspace上运行相同的脚本,也在EC2上运行以进行测试。该脚本将使用http.request连接到:Google,Facebook,以及我的另一个脚本,它只是输出由另一个EC2实例托管的数据(如hello world)。
测试工具我只是桌面上的jMeter。
pre-node.js测试: jMeter - > Google搜索结果:快速且一致。 jMeter - > Facebook结果:快速而稳定。 jMeter - >我的简单输出脚本结果:快速且一致。
然后我用100个循环制作50个Concurrent Threads / sec,测试我的Rackspace nodejs,然后测试具有相同性能问题王的EC2 node.js jMeter - > node.js - >谷歌搜索结果:在200个重新设置中从50毫秒到2000毫秒 jMeter - > node.js - > Facebook结果:在200次重新设定之后,从200毫秒变为3000毫秒 jMeter - > node.js - >我的简单输出脚本结果:在200次重新设置后,从100毫秒到1000毫秒 前10-20个请求很快,然后开始减速。
然后,当我更改为10个并发线程时,事情开始发生变化..响应非常一致,没有减速。
与Node.js(http.request)可以处理的并发线程数有关。
------------ 更多 --------------
我今天做了更多测试,这里是: 我使用了http.Agent并增加了最大套接字。然而,有趣的是,在一个测试服务器(EC2)上,它改进了很多而且没有更慢。 HOwever,另一台服务器(rackspace)只有一点点改进。它仍显示减速。我甚至在请求标题中设置了“Connection:close”,它只提高了100ms。
如果http.request使用连接池,如何增加它?
在两个服务器中,如果我执行“ulimit -a”,则打开的文件数为1024.
------------- ** MORE AND MORE ** ------------------- < / p>
似乎即使我将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'
}**
};
如果我将其设置为“Connection”:“close”,则响应时间将慢100倍。
有趣的事情发生在这里:
1)在EC2中,当我第一次使用Connection进行测试时:保持活动状态,大约需要20-30毫秒。然后,如果我更改为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和http.js&amp; https.js修复自https://github.com/mikeal/node/tree/http2
性能更好,更稳定。
答案 0 :(得分:8)
我用
解决了这个问题require('http').globalAgent.maxSockets = 100000
或
agent = new http.Agent()
agent.maxSockets = 1000000 # 1 million
http.request({agent:agent})
答案 1 :(得分:3)
我正在努力解决同样的问题。我发现我的瓶颈是DNS的东西,虽然我不清楚在哪里/为什么。如果我向http://myserver.com/asd之类的请求发出请求,我几乎无法运行50-100 rq / s,如果我超过100 rq / s并且更多事情变得灾难,响应时间变得非常大并且一些请求永远不会完成无限期等待,我需要杀死-9我的服务器。如果我向服务器的IP地址发出请求,一切都稳定在500 rq / s,虽然不是很平滑,图形(我有实时图表)是最高的。请注意,Linux中打开文件的数量仍有限制,我设法打了一次。另一个观察是单节点过程不能平滑地产生500 rq / s。但我可以启动4个节点进程,每个进程200 rq / s,我得到非常流畅的图形和一致的CPU /净负载和非常短的响应时间。这是节点0.10.22。
答案 2 :(得分:1)
这不一定会解决您的问题,但它会稍微清理您的代码并以您应该的方式利用各种事件:
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');
我删除了身体的输出。由于我们从一个插槽流到另一个插槽,因此我们无法确保在不缓冲的情况下随时查看整个机身。
编辑:我相信节点正在使用http.request的连接池。如果您有50个并发连接(因而有50个并发的http.request尝试),您可能会遇到连接池限制。我目前没有时间为您查看,但您应该查看有关http的节点文档,尤其是http代理。
编辑2:关于node.js邮件列表上的一个非常类似的问题有a thread。你应该看看它,特别是Mikael的帖子应该是有意义的。他建议通过将选项agent: false
传递给http.request
调用来完全关闭请求的连接池。我没有任何进一步的线索,所以如果这没有帮助,你可以尝试在node.js邮件列表上获得帮助。
答案 3 :(得分:1)
Github问题877可能是相关的:
https://github.com/joyent/node/issues/877
虽然我不清楚这是不是你要打的。当我点击时,“agent:false”解决方法对我起作用,就像在请求中设置“connection:keep-alive”标题一样。