为在node.js应用上运行的mongodb计算n个连接池所需的内存

我试图剖析当前configuration为使用50个连接池的运行mongodb的node.js应用程序的性能。 使用Blazemeter我一直试图做一个testing,发送1000个模拟用户到我的端点。 运行在一个较小的亚马逊ec2实例(4个CPU和7.5 GB的内存,性能似乎是CPU绑定)。 当我开始向具有至less8个以pm2集群模式运行的CPU的大型机器移动时,似乎mongodb的内存不足。 当testing达到约300-500个模拟用户时,mongo进程将失败:

IE我从所有的数据库查询中得到一个错误,当我尝试启动mongo shell时,我看到以下消息:

2015-10-26T23:34:56.657+0000 warning: Failed to connect to 127.0.0.1:27017, reason: errno:111 Connection refused 2015-10-26T23:34:56.658+0000 Error: couldn't connect to server 127.0.0.1:27017 (127.0.0.1), connection attempt failed at src/mongo/shell/mongo.js:146 exception: connect failed 

第一次发生这种情况时,我在mongo日志中也发现了以下错误:

 exception in initAndListen: 10309 Unable to create/open lock file: /var/lib/mongodb/mongod.lock errno:13 Permission denied Is a mongod instance already running?, terminating 

在下面的testing中,我只看到上述行为,但在mongo日志中没有看到任何错误。

运行这些testing时,mongo通常最终会在失败之前使用大约80%的系统内存。

以下是此端点使用的唯一mongo查询:

  utility.getNextId(db, "projects", function(err, counter) { var pid = counter.seq; var newProject = { name: projectName, path: "/projects/"+user.name+"/"+projectName, created: utility.now(), modified: utility.now(), uid: user.uid, pid: pid, ip: ip } // Hierarchy of cloned projects if( parentPid ) newProject.parent = parentPid; db.collection("projects").insert(newProject, function(err, inserted) { db.collection("users").update( {uid: user.uid}, {$addToSet: { projects:pid }}, function(err,_) { callback(err, newProject); } ); }); }); }; exports.getNextId = function(db, name, callback) { db.collection("counters").findAndModify( {_id:name}, [["_id","asc"]], {$inc : {"seq":1}}, {upsert:true, new:true}, function(err, object) { callback(err, object); } ); }; 

大部分的testing是在一个amazon ec2 m4.4xlarge(16 cpu和64GB ram)上完成的。

具有64GB RAM的机器的连接池大小为50到大? 我想不会。 有没有一种很好的方法来计算n个连接池所需的内存量? 我的问题与我正在做的问题?

编辑:这是一个屏幕截图显示mongostat权利作为mongo崩溃的亚马逊ec2 m4.4xlarge 16cpus和64GB的RAM

在这里输入图像描述

我们在顶部创buildmongo数据库与其他许多要求:

 var mongo = require("mongodb"); var flash = require("connect-flash"); var session = require("express-session"); var auth = require("basic-auth"); var admin = require("./admin.js"); var mongoServer = new mongo.Server("localhost", 27017, {auto_recconnect:true, poolSize: 50}); var db = new mongo.Db("aqo", mongoServer, {safe:true}); var busboy = require('connect-busboy'); db.open(function(err,db) { if(err) console.warn("mongo-open err:",err); }); 

编辑:这是我的用户集合的索引:

 [ { "v" : 1, "key" : { "_id" : 1 }, "name" : "_id_", "ns" : "aqo.users" }, { "v" : 1, "key" : { "uid" : 1 }, "name" : "uid_1", "ns" : "aqo.users" } ] 

对于一台64GB RAM的机器,虽然50的池大小不算大,但800当然是。 那是因为你的节点进程有16个实例,每个运行50个实例。 最大连接数的默认值是可用文件描述符的80%。 如果您使用的是Linux,则默认值为1024,因此您已经打开了几乎最大的连接。 此外,每个连接的开销约为10MB,因此您只需使用8GB左右的连接。 这显然不理想。

理想情况下,您应该尽可能在连接池中重用这些连接。 因此,开始负载testing,将poolSize设置为默认值5.(即实际为16 * 5 = 80)。 您可以信任pm2以循环方式处理负载,并且每个实例的池大小5应该完美无缺,并为您提供最佳性能。 如果5还不够,请稍等一下,直到find合适的东西。

您有大量的排队读取,并没有成功发生多次读取。 我的猜测是users集合中的uid没有索引(因为您在其他地方用_id查询,Mongo会自动索引)。

它也看起来像你正在运行的Mongo作为一个独立的服务器,它的目的是作为副本集运行,我不知道这会造成什么问题,但我猜测他们没有做一个单一的Mongo实例的testing自己工作,所以可能会有记忆问题。