猫鼬在未指定的时间段后停止响应

Luc*_*Jay 6 azure mongoose mongodb node.js

自从我开始开发项目(12个月前!)以来,我一直在为解决这个问题而烦恼不已,总是假设在准备发布之前我会找到答案的……不幸的是,事实并非如此!

基本上,我有一个运行在Azure上的相当简单的node.js服务器,使用mongoose连接到MongoLab(现为MLab)数据库。

连接代码如下所示:

// Connect to DB
//mongoose.set('debug', true);
mongoose.connect(envConfig.app.db, {
    server: {
        auto_reconnect: true,
        socketOptions: {
            keepAlive: 1,
            connectTimeoutMS: 30000,
            socketTimeoutMS : 30000,
        }
    },
    replset: {
        auto_reconnect: true,
        socketOptions: {
            keepAlive: 1,
            connectTimeoutMS: 30000,
            socketTimeoutMS : 30000,
        }
    }
}, function (err) {
    if (err) winstonLogger.error(err);
});
mongoose.connection.on('connecting', function () {
    console.log('Connecting to MongoDB...');
});
mongoose.connection.on('connected', function () {
    console.log('MongoDB connected!');
});
mongoose.connection.on('open', function () {
    console.log('MongoDB connection opened!');
});
mongoose.connection.on('error', function (err) {
    console.error('Error in MongoDb connection: ' + err.stack);
    winstonLogger.error(err);
    mongoose.disconnect();
});
mongoose.connection.on('disconnected', function () {
    winstonLogger.error('MongoDB disconnected!');
    mongoose.connect(envConfig.app.db, {
        server: {
            auto_reconnect: true,
            socketOptions: {
                keepAlive: 1,
                connectTimeoutMS: 30000,
                socketTimeoutMS : 30000,
            }
        },
        replset: {
            auto_reconnect: true,
            socketOptions: {
                keepAlive: 1,
                connectTimeoutMS: 30000,
                socketTimeoutMS : 30000,
            }
        }
    });
});
mongoose.connection.on('reconnected', function () {
    console.log('MongoDB reconnected!');
});
mongoose.connection.on('close', function () {
    console.log('MongoDB closed');
});
Run Code Online (Sandbox Code Playgroud)

您看到的所有其他超时选项等都是我解决此问题的尝试(无济于事)。

这是一个典型的请求:

AccessToken.findOne({ token: token })
            .maxTime(10000)
            .exec(function (err, accessToken) {
                // If I even got to here I would be happy
                if (err) return done(err);
                // If I could consistently get to here, my project would be finished and I would enjoy being alive again
            });
Run Code Online (Sandbox Code Playgroud)

因此,当我启动服务器时,一切正常。而且它保持良好的运行状态……有时持续数天,有时数小时,有时数分钟。但是,在某个时候,一个请求将命中该代码,并且只会...挂起。没有超时,没有错误。只是娜达 我没有在任何日志中找到任何证据来显示正在发生的一切证据。我的快递记录仪终于放弃了,我得到了类似的东西:

POST /api/auth/verify - - ms - -
Run Code Online (Sandbox Code Playgroud)

因此,在这一点上,我唯一的选择是重新启动服务器,因为我无法获得出于爱情或金钱而无法完成的数据库请求(或超时或显示错误)。

我搜寻互联网已经一年了,希望找到解决方案,但是我尝试过的一切都导致了……没有任何结果……同样的结果。我什至尝试在Azure上运行自己的副本集,而不是使用MongoLab。同样的问题。我唯一的想法是这是一个Azure问题,没有明显的解决方案,但是我真的不热衷于寻找其他主机。话虽如此,我什至不知道为什么Mongoose请求不超时或不显示任何错误,即使我已经设置了maxTime ...

以下是来自MongoLab的一些有关我认为可能是问题的信息:http ://docs.mlab.com/connecting/#known-issues ,但是如您所见,我已经尝试了他们提出的所有建议,甚至更多,没有成功。

我真的很茫然,整个情况同时令人麻木,令人心碎,令人难以置信。

如果外面有任何想法,我将永远爱你...

先感谢您!

-卢克

小智 2

这听起来很像我几个月来在相同的设置(Azure 上的 NodeJ、Mongoose、MongoLab 副本集)上遇到的问题。这无疑是“同时令人大脑麻木、心碎又令人难以置信的愤怒”。经过几个小时的挫折后,我终于在几个月前解决了这个问题......

我发现它是由副本集故障转移触发的。这是通过使用 Azure 上的测试服务器和 MongoLab 上的测试副本集并在 Mongolab 上手动触发故障转移来验证的(我无法通过在本地运行 NodeJs 服务器和 MongoDB 实例来重现,因为问题与连接时间有关)。

本应帮助 Mongoose 在故障转移后连接到辅助服务器的高可用性检查未正确运行。由于某种竞争条件,如果服务器在初始化 Mongoose 连接后需要一段时间才能启动,则在 mongodb-core 中启动检查的回调会失败。

我最终所做的是将 Mongoose 连接尽可能晚地移到服务器启动过程中。它曾经是在一个相当大的文件缩小任务之前进行的,这可能是问题所在。

希望这可以帮助!

我的猫鼬设置:

// Options
mongooseOptions.replset = {
  ha: true, // Make sure the high availability checks are on
  haInterval: 5000, // Run every 5 seconds
  socketOptions : {
    ... // nothing special here
  }
}

mongoose.connect(mongodb_uri, mongooseOptions);

// Make sure the high availability checks are occuring
// Should see "replset ha start" "replset ha end" pairs every 5 secs
// Well, hopefully.
if (mongoose.connection.db.serverConfig.s.replset) {
  mongoose.connection.db.serverConfig.s.replset.on('ha', function(type, data) {
    console.log('replset ha ' + type);
  })
}
Run Code Online (Sandbox Code Playgroud)