MongoDB拒绝高容量(10000)插入/写入的连接

时间:2013-03-27 21:25:09

标签: javascript node.js mongodb

我们通过Node.js应用程序插入数据并使用node-mongodb-native库连接到mongodb。 Mongo DB分片,共有5个分片。节点和mongos实例包含在具有14980MB RAM的四核AWS实例上。两个分片和配置服务器 包含在单个核心实例中,其余三个分片位于具有单个核心处理器的不同实例上。

我们可以使用Node.js测试脚本在9秒内有效地同时插入1000条记录。

对于10000个并发插入,其中约有2000个失败并返回以下错误消息:

    [Error: failed to connect to [ip address of mongos]]

在此10000插入过程中,前5000或6000次插入成功且没有错误。 在此期间,CPU使用率仍然相对较低(使用率为13%)。然后,一个核心上的CPU跳跃到大约75%,而MongoDB会抛出 错误消息拒绝连接。在插入一些失败之后,一些写入会间歇性地成功。

我们在linux上将ulimit -n设置为20000。我们在Node.js api中的insert函数中传递了poolSize = 5参数。

var responseHandlers = require('./responseHandlers')
    ,schemaValidation = require('./schemaValidation')
    ,mongoDb = require('mongodb')
    ,md5 = require('MD5')
    ,ObjectID = require('mongodb').ObjectID;

function insert(data, timestamp, response) {
  // validating the data to be inserted
  schemaValidation.validate(data, function(err) {
    if(err) {
      console.log(err);
      responseHandlers.invalidRequest(response, 2); 
    } else {
      //console.log("opening db..");
      server = new mongoDb.Server(mongoConfig.host,mongoConfig.port,{'auto_reconnect': true, 'poolSize': 5});
      db = new mongoDb.Db(mongoConfig.database, server, {w: 1});
      db.open(function(err, db) {
        if(err) { 
          console.log(err);
          responseHandlers.invalidRequest(response, 2); 
        } else {
          db.collection(mongoConfig.collection, function(err, collection) {
            if(err) {
              console.log(err);
              responseHandlers.invalidRequest(response, 2); 
            } else {
              //going to instantiate document fields
              var time = new Date().getTime(),
              oid = new ObjectID(),
              hash = md5(oid.toHexString()),
                            obj = {'data_utc' : timestamp, 'server_utc' : time, '_id' : oid,    'hash' : hash}; 
                            obj.data = data;
              //inserting..
              collection.insert(obj, {w:1}, function(err, result) {
                if(err) {
                  console.log(err);
                  responseHandlers.invalidRequest(response, 2); 
                } else {
                  console.log('Insert successful');
                  responseHandlers.validRequest(response, false, result);
                }   
              db.close();
              }); 
            }   
          }); 
        }   
      });   
    }   
  }); 
}   
exports.insert = insert;

任何人都可以帮助解决为什么拒绝连接,无法插入?为什么会这样 对于一部分插入物而言,大约中途失败了吗?

2 个答案:

答案 0 :(得分:0)

要解决此问题,您应该观察mongod控制台中打开的连接数。根据您提供的代码示例,您可能在每个插入上打开一个新的mongodb连接。要更正此问题,请尝试将“服务器”的实例化移动到您用于调用此函数的控制循环范围之外。

答案 1 :(得分:0)

您似乎在循环中创建了太多连接。 Best将创建一个mongoDB客户端的singelton实例,并为每个更新使用相同的对象并插入集合中。 MongoDB对连接池有限制,默认大小为5个连接。之后的任何尝试都会拒绝服务器,但是您可以增加默认的连接池大小,但这样做并不是一个好主意。
另一点需要注意的是,MongoDB:执行并发写入的线程数量有限,性能更好。对于集合中的写入(使用最新的驱动程序3.2),mongoDB对集合执行行级锁定。它一次获取1000条记录的锁定,并使用正在更新的记录滑动锁定。因此,如果您将更多并发线程用于并行操作,它最终将等待锁定被释放。最好使用2个线程进行写入,或者最多进行4个,大小为20k或40K。

您可以考虑实现受控读写的生成器/消费者模式。

详细阅读请点击此处:https://mongodb.github.io/node-mongodb-native/driver-articles/mongoclient.html