Nuc*_*eon 5 sockets mongodb node.js
当我们并行进行大量连接时,我们会遇到 mongodb 套接字关闭的问题。
这是一个测试脚本:
var mongodb = require("mongodb");
var async = require("async");
mongodb.MongoClient.connect("mongodb://mongo-dev1:27017/test", function(err, db) {
if (err) { throw err; }
var calls = [];
var col = db.collection("test");
var count = 10000;
for(var i = 0; i < count; i++) {
(function(i) {
calls.push(function(cb) {
console.time("update_" + i);
col.update({ i : i }, { i : i }, { upsert : true }, function(err) {
console.timeEnd("update_" + i);
cb(err);
});
});
})(i);
}
async.parallel(calls, function(err) {
if (err) { throw err; }
console.log("done");
});
});
Run Code Online (Sandbox Code Playgroud)
如果我运行该脚本,它将失败并出现以下错误MongoError: server mongo-dev1:27017 sockets closed
mongodb本身的日志输出是
SocketException handling request, closing client connection: 9001 socket exception [SEND_ERROR] server [192.168.1.111:53556]
我无法弄清楚是什么机制导致套接字关闭。我相信等式的 Node 端挂起,因为我的事件计时显示 Node close 事件发生在 mongodb 日志中的 SocketException 之前几毫秒。我已经进入mongodb
包mongodb-core
并做了一些console.log
,该事件的发起者是at TCP.close (net.js:485:12)
。这告诉我套接字本身正在关闭。基于此,确实感觉 Linux 本身正在关闭套接字或 mongoDB 主机箱,而不是 Node 或 MongoDB 正在这样做。但我不确定如何证明这一点。
这是我考虑过但已排除的第一组选项:
套接字超时 - 如果是超时,错误消息会有所不同,我通过socketTimeoutMS
在构造连接时传递选项来验证这一点。如果我传递一些小东西,我会收到超时错误。
MongoDB 失去连接 - 如果我使用监控 mongodb replset 上的连接,db.serverStatus().connections
我仍然有大量可用连接。
当我与本地主机非副本集通信时,不会复制此行为。这可能是本地主机的事情,也可能是副本集的事情。
如果我将并行更改为 parallelLimit 100,则可以顺利完成。由于 Node 使用连接池,无论我并行发送 1000 个连接还是一次并行发送 100 个连接,它都应该向 MongoDB 提供相同的流量,因为它们都被强制进入相同的 10 个套接字。这有助于指导我这是一个节点问题。
使用节点 10、节点 12 和 MongoDB 2.6
小智 2
我在重负载下遇到了同样的问题,但是当深入研究 mongodb 驱动程序时,我发现 socketTimeout 和 connectTimeout 的默认值设置为 30000 ms。
提高它们都解决了我的问题:
mongodb://m1.url.xyz:27017,m2.url.xyz:27017/test?replicaSet=myset&connectTimeoutMS=300000&socketTimeoutMS=300000&readPreference=secondary
Run Code Online (Sandbox Code Playgroud)
(确保 ulimit 设置和 net.ipv4.tcp_keepalive_time 针对 mongodb 进行了优化) http://docs.mongodb.org/manual/faq/diagnostics/
归档时间: |
|
查看次数: |
4436 次 |
最近记录: |