我正在使用NodeJ构建实时统计应用程序。对于原型,我在RackSpace服务器中使用四核AMD Opteron,使用Cluster NodeJs(http://learnboost.github.com/cluster/)和使用本机nodejs驱动程序的MongoDb对nodejs服务器进行测试。
基本上我在公司项目中插入了一个JS代码,为一堆客户的网站提供内容。这段代码“ping”我的服务器每10秒调用一个图像并传递我在服务器端获得的参数并在MongoDb集合中插入(或更新)。在一天的“慢”时间里,我得到大约3000个连接(我在终端上使用netstat -natp命令获得这些连接)每次使我的集群使用大约25%的每个核心(我使用“top”命令获得这些)。但是在一个“忙碌”的时刻,我每次获得大约7000多个连接,这使得我的集群变得疯狂(大约80%+使用每个核心),而且随着时间的推移,节点似乎会降级。 这是正常的吗?或者Nodejs应该以更“简单”的方式处理这些命中?如果我使用Mongoose,性能会增加吗?
如果你对MongoDb感到好奇,它会占用一个核心的4%左右,这对我来说很好(没有使用索引,使用率约为50%+,但至少,索引解决了这个性能问题)。
非常感谢耐心, 欢呼声。
编辑:
使插入的代码如下所示: db.open(function(err,db){});
return connect.router(function(app){
app.get("/pingserver/:clientid/:event/:cachecontrol", function(req, res, next){
event:'+req.params.event + ', cachecontrol:' + req.params.cachecontrol);
var timestamp = new Date();
switch(req.params.event) {
case 'load':
var params = url.parse(req.url, true).query;
db.collection('clientsessions', function(err, collection) {
try {
var client = {
id: req.params.clientid,
state: req.params.event + 'ed',
loadTime: timestamp.getTime(),
lastEvent: req.params.event,
lastEventTime: timestamp.getTime(),
lastEventDate: timestamp.toString(),
events: [{
event: req.params.event,
timestamp: timestamp.getTime(),
date: timestamp.toString()
}],
media: {
id: params.media.split('|')[0] || null,
title: unescape(params.media.split('|')[1]) || null
},
project: {
id: params.project.split('|')[0] || null,
name: unescape(params.project.split('|')[1]) || null
},
origin: req.headers['referer'] || req.headers['referrer'] || '',
userAgent: req.headers['user-agent'] || null,
userIp: req.socket && (req.socket.remoteAddress || (req.socket.socket && req.socket.socket.remoteAddress)),
returningUser: false
};
}catch(e) {console.log(e);}
collection.insert(client, function(err, doc) {
});
});
break;
case 'ping':
db.collection('clientsessions', function(err, collection) {
collection.update({id: req.params.clientid}, {
$set : { lastEvent: req.params.event
,lastEventTime: timestamp.getTime(),lastEventDate: timestamp.toString()}
}, {}, function(err, doc) {});
});
break;
default:
db.collection('clientsessions', function(err, collection) {
collection.update({id: req.params.clientid}, {
$set : {state: req.params.event+'ed'
, lastEvent: req.params.event
, lastEventTime: timestamp.getTime()}
, $push : { events : { event: req.params.event, timestamp: timestamp.getTime(), date: timestamp.toString() } } }, {}, function(err, doc) {});
});
break;
}
if (!transparent) {
console.log('!transparent');
transparent = fs.readFileSync(__dirname + '/../../public/images/transparent.gif', 'binary');
}
res.setHeader('Content-Type', 'image/gif');
res.setHeader('Content-Length', transparent.length);
res.end(transparent, 'binary');
});
});
答案 0 :(得分:2)
这是正常的吗?
取决于,他们自己的联系会消失吗?他们只是继续建设吗?你在谈论“网络连接”(http)或MongoDB连接吗?
mongod
日志说什么? node
日志说什么?
您每秒收到多少请求?
或者Nodejs应该以更“简单”的方式处理这些命中?
很难说不知道代码在做什么。
您希望盒子处理多少个同时连接?
如果我使用Mongoose,性能会提高吗?
所以Mongoose实际上是node-mongodb-native
驱动程序的对象包装器。它不是一个不同的驱动程序,它只是一个包装器。
包装器将代码添加到您已有的代码中。如果您遇到代码问题,则无法保证添加代码可以更好地解决问题。如果mongoose确实解决了你的问题,那么它正在做一些与你不相关的事情。如果是这种情况,您不一定需要Mongoose,您只需要更好的连接管理。
看看有很多潜在的问题来源。
解决这个问题的唯一方法就是打破碎片并深入挖掘细节。开始的地方:
- 正确关闭MongoDB的连接(查看数据库日志)?
- 日志是否包含任何其他错误?
- 为节点日志做同样的事情?
- 你有关于内存使用情况的图表吗?谁占用了最多的记忆?
- 当你达到每个核心的80%时,哪个进程正在执行此操作? mongod
? node
?别的什么?
为了真正帮助你,我们需要更多关于系统发生情况的数据。
答案 1 :(得分:1)
连续请求可能非常昂贵,尤其是当它们之间的超时很小时。在您的情况下,您接受每秒约300-700 +并发请求,您的系统负载可能取决于您正在处理什么。您可以尝试切换到Mongoose,但是如果它适用于您的场景,我宁愿查看图像处理和缓存,因为DB似乎不是您的瓶颈(尽管DB驱动程序也可能是问题)。
答案 2 :(得分:1)
if (!transparent) {
console.log('!transparent');
transparent = fs.readFileSync(__dirname + '/../../public/images/transparent.gif', 'binary');
}
透明假的频率是多少?我没有看到它在代码中定义。您正在阻止同步磁盘IO上的整个Node进程,可能对每个请求都是如此。为什么?如果必须从磁盘读取文件,请异步执行。如果文件是静态的和小的,也许你应该把它加载到内存中一次。
答案 3 :(得分:1)
节点的http
服务器默认保持活动状态。在您的情况下,它会导致太多无用的连接。只需尝试向disable Keep-Alive
添加标头 - 具有群集的普通节点就可以了。
res.setHeader("Connection", "close")
答案 4 :(得分:0)
只是更新:
我已经删除了群集并在服务器上放置了Nginx层。因此,“降级”需要花费更长的时间,但它仍在这样做,特别是消耗了大量的系统内存。 有什么想法吗?
非常感谢所有答案!
编辑: 重新做了一些测试。我认为主要问题是关于开放的联系。当我在Nginx端口上运行netstat时,它就像2000连接一样。当我在每个nodejs应用程序端口上运行时,它会显示2000(或更多)。基本上我的“最佳情况”是nodejs应用程序上的打开连接的总和将匹配Nginx端口上的打开连接,对吧?我认为这是主要问题,它正在影响巨大的“time_wait”状态。
答案 5 :(得分:0)
你可能也想在缓冲区中提供透明的gif,如下所示: