【问题标题】:Mongodb server sockets closed on replSet在 replSet 上关闭的 Mongodb 服务器套接字
【发布时间】:2016-01-20 01:15:43
【问题描述】:

当我们进行大量并行连接时,我们遇到了关闭 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");
    });
});

如果我运行该脚本,它将失败并出现以下错误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]

我不知道是什么机制导致套接字关闭。我相信等式的节点方面已经挂起,因为我的事件时间显示节点关闭事件发生在 mongodb 日志中的 SocketException 之前几毫秒。我已经进入mongodb 包到mongodb-core 并做了一些console.log 并且事件的发起者是at TCP.close (net.js:485:12)。这告诉我套接字本身正在关闭。基于此,感觉就像 linux 本身正在关闭套接字或 mongoDB 主机盒,而不是 Node 或 MongoDB 正在这样做。我不确定如何证明这一点。

这是我考虑过但已排除的第一组选项:

  1. 套接字超时 - 如果是超时,则错误消息不同,我在构建连接时通过传递 socketTimeoutMS 选项验证了这一点。如果我传递一些小的东西,我会收到超时错误。

  2. MongoDB 连接不足 - 如果我使用 db.serverStatus().connections 监控 mongodb replset 上的连接,我仍然有大量可用连接。

  3. 当我与本地主机非副本集通信时,此行为不会复制。这可能是 localhost 的事情,也可能是副本集的事情。

  4. 如果我将并行更改为 100 的并行限制,则它会顺利完成。由于 Node 使用连接池,无论我是并行发送 1000 个还是一次并行发送 100 个,它应该相当于 MongoDB 的相同流量,因为它们都被强制进入相同的 10 个套接字。这有助于指导我这是一个节点问题。

使用节点 10、节点 12 和 MongoDB 2.6

【问题讨论】:

  • 我偶尔会在生产中遇到同样的异常(使用 Mongo 3.0.3 副本集)。到目前为止我还没有找到解决方案。一个观察结果是,当主服务器负载过重时,这些异常更有可能发生......
  • 我也有类似的观察。如果我在我们的实时服务器上执行此测试,则在我开始关闭套接字之前的阈值大约是 1000 个并行,而在我们的开发环境中约为 7000 个,没有潜在负载。
  • 我希望 MongoDB 团队中的某个人能对此有所了解。我个人认为 MongoDB 在收集触发每个副本集故障转移的数据方面需要做得更好。我希望有一个简单的命令可以在 Mongo 决定故障转移时转储所有关键资源的状态。目前很难判断特定硬件资源是否存在瓶颈、网络故障或某些疯狂查询等。
  • 我有一个非常相似的情况,同样的套接字关闭问题,并且无法在任何地方找到一个好的答案。希望有人能解释一下。
  • 在终端中放入 db.serverStatus().connections 会得到什么?

标签: node.js mongodb sockets


【解决方案1】:

我在重负载下遇到了同样的问题,但是在深入研究 mongodb 驱动程序时,我发现 socketTimeout 和 connectTimeout 的默认值设置为 30000 毫秒。

提高它们都解决了我的问题:

mongodb://m1.url.xyz:27017,m2.url.xyz:27017/test?replicaSet=myset&connectTimeoutMS=300000&socketTimeoutMS=300000&readPreference=secondary

(确保 ulimit 设置和 net.ipv4.tcp_keepalive_time 已针对 mongodb 进行了优化) http://docs.mongodb.org/manual/faq/diagnostics/

【讨论】:

    【解决方案2】:

    通过网络连接到副本集并在数据库初始化脚本中快速发出大量查询时,我遇到了同样的问题。

    当连接到同一台计算机上的单个 mongodb 实例时,一切正常,但通过网络连接到副本集,即使只有 2-3 毫秒的延迟,它也会引发套接字关闭错误。

    我还在注册表中将两台计算机上的保持活动时间更改为 120。 MongoDB 3.0.6服务器在Windows Server 2012,应用机在Windows 10。

    然后我尝试了,没有效果(先重启副本集上的mongod服务)

    然后我将?connectTimeoutMS=120000&amp;socketTimeoutMS=120000 部分添加到查询字符串中,我在网络上使用副本集取得了成功。

    当我查看有关选项的文档时,我发现 单个 实例服务器的默认超时为 30000 毫秒,但对于 副本集,默认超时为 0 毫秒

    输入:http://mongodb.github.io/node-mongodb-native/2.1/reference/connecting/connection-settings/

    请参阅:副本集级别选项

    socketOptions.connectTimeoutMS {Number, default: 0} TCP Connection timeout setting. socketOptions.socketTimeoutMS {Number, default: 0} TCP Socket timeout setting.

    这是 node.js 驱动程序的文档。我在 mongoose 文档上找不到关于套接字超时和连接只有 6-7 个其他选项的信息。我目前假设猫鼬会逐字传递您指定的选项,而不是将某些选项列入白名单。那么您可以在选项对象中指定超时时间而不是连接字符串。

    【讨论】:

    • 我没有看到您在提供的链接中建议的 connectTimeoutMS = 0 和 socketTimeoutMS = 0 的建议超时。自发布您的答案后是否已更新?
    猜你喜欢
    • 2011-11-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-08
    • 2017-08-05
    • 2013-01-22
    • 1970-01-01
    相关资源
    最近更新 更多