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

自从我开始开发我的项目(12个月前!)以来,我一直在嘲笑这个问题,总是假设在我准备发布前我会find答案…不幸的是,情况并非如此!

基本上,我有一个相当直接的在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'); }); 

所有额外的超时选项,等你看到的是我的尝试解决这个问题的一部分(无济于事)。

这是一个典型的要求:

 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 }); 

所以,当我启动我的服务器时,一切都很好。 而且它一直工作得很好…有时几天,有时几小时,有时几分钟。 然而,在某些时候,一个请求会打到这个代码,它会…挂起。 没有超时,没有错误。 只是虚无。。 我没有在任何日志中发现任何证据certificate发生了什么事。 我的快速logging器终于放弃了,我得到了这样的东西:

 POST /api/auth/verify - - ms - - 

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

我已经在互联网上search了一年,希望得到一个解决scheme,但是我所尝试过的一切都导致了……没有……相同的结果。 我甚至尝试在Azure上运行自己的副本集,而不是使用MongoLab。 同样的问题。 我唯一的想法是,这是一个没有明显解决scheme的Azure问题,但我真的不热衷于find另一个主机。 这就是说,我不明白为什么Mongoose请求不会超时或显示任何错误,即使我已经设置了一个maxTime …

下面是MongoLab关于我认为可能是问题的一些信息: http ://docs.mlab.com/connecting/#known-issues,但正如你所看到的,我已经尝试了他们所build议的一切,还有更多,没有成功。

我真的不知所措,整个情况同时令人感到头脑麻木,令人心碎,令人难以置信的令人不快。

如果有人有任何想法,我会永远爱你…

先谢谢你!

路加福音

这听起来像一个问题,我已经有几个月的相同的设置(Azure,Mongoose,MongoLab副本集上的NodeJs)。 当然,这是“同时令人麻木,令人心碎和令人难以置信的愤怒”。 几个月前我终于解决了这个问题,经过了很多小时的挫折…

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

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

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

希望这可以帮助!

我的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); }) } 

好的,所以我现在还没有这个问题。 我对连接设置进行了很多小改动,但是我认为最大的影响是要么明确地设置ha(高可用性)和haInterval replset选项,要么可能将连接代码移动到我的app.js的最后。

以下是最终连接代码的样子:

 // Connect to DB var connectionOptions = { replset: { socketOptions: { connectTimeoutMS: 300000, // 5 minutes keepAlive: 120 }, ha: true, // Make sure the high availability checks are on haInterval: 10000, // Run every 10 seconds } }; //mongoose.set('debug', true); mongoose.connect(envConfig.app.db, connectionOptions, 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) { winstonLogger.error(err); mongoose.disconnect(); }); mongoose.connection.on('disconnected', function () { winstonLogger.error('MongoDB disconnected!'); mongoose.connect(envConfig.app.db, connectionOptions, function (err) { if (err) winstonLogger.error(err); }); }); mongoose.connection.on('reconnected', function () { console.log('MongoDB reconnected!'); }); mongoose.connection.on('close', function () { winstonLogger.error('MongoDB closed'); }); if (mongoose.connection.db.serverConfig.s.replset) { mongoose.connection.db.serverConfig.s.replset.on('ha', function(type, data) { console.log('replset ha ' + type); }); mongoose.connection.db.serverConfig.s.replset.on('timeout', function () { winstonLogger.error('MongoDB timeout'); }); } 

我还打开了Azure WebApp的AlwaysOn选项(这似乎没有太大的作用,但是现在我没有把它关掉,它正在工作!)。

似乎这个问题与故障切换后不重新连接有关,但我不能100%确定地说。

希望这会帮助其他人遇到同样的问题…希望我没有跳过枪只让它在几天内停止工作(如果发生的话,我会回来的!)。

感谢大家提供了一个build议,我是ETERNALLY感恩:)

根据我的经验,我build议你可以ping Mlab上的mongodb,以确定在webapp挂起时是否用完Mongo连接。

我认为你可以尝试为mongoose连接添加连接池选项,就像@BlakesSeven所说的那样。 请参阅“ Connection pools的Mongoose指导主题Connections来configuration池大小。