我们通过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;
任何人都可以帮助解决为什么拒绝连接,无法插入?为什么会这样 对于一部分插入物而言,大约中途失败了吗?
答案 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