自从我开始开发我的项目(12个月前!)之后,我一直在解决这个问题,总是假设在我准备发布之前我会找到答案...不幸的是,那不是情况下!
基本上,我有一个相当简单的node.js服务器在Azure上运行,使用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
});
所以,当我启动我的服务器时,一切都很好。并且它保持良好的工作...有时几天,有时几小时,有时几分钟。但是,在某些时候,请求会触及此代码,它只会...挂起。没有超时,没有错误。只是虚无...我没有在任何日志中找到任何证据来证明发生了什么。我的快速记录器终于放弃了,我得到了类似的东西:
POST /api/auth/verify - - ms - -
所以在这一点上,我唯一的选择是重新启动服务器,因为我无法获得数据库请求来完成(或超时,或显示错误)的爱情和金钱。
我已经在互联网上搜索了一年希望得到一个解决方案,但我所尝试的一切都导致......没有......同样的结果。我甚至尝试在Azure上运行我自己的副本集而不是使用MongoLab。同样的问题。我唯一的想法是,这是一个没有明显解决方案的Azure问题,但我真的不热衷于寻找另一个主机。话虽这么说,我不明白为什么Mongoose请求不会超时或显示任何错误,即使我设置了maxTime ......
以下是MongoLab关于我认为可能出现的问题的一些信息: http://docs.mlab.com/connecting/#known-issues, 但正如你所看到的,我已经尝试过他们所建议的一切,而且还有更多,但没有成功。
我真的很茫然,整个情况同时让人头脑麻木,令人心碎,令人难以置信的真气。
如果有人有任何想法,我会永远爱你...
提前谢谢!
路加福音
答案 0 :(得分:4)
好的,所以我暂时没有问题。我对连接设置进行了很多小的更改,但我认为最大的影响是显式设置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%确定地说。
希望这能帮助遇到同样问题的其他人...并且希望我没有跳过枪只让它在几天内再次停止工作(如果发生这种情况我会回来的!)
感谢所有提出建议的人,我非常感激:)
答案 1 :(得分:2)
这听起来很像我几个月来使用相同设置的问题(Azure上的NodeJ,Mongoose,MongoLab副本集)。肯定是“同时脑筋麻木,令人心碎,令人难以置信的真气”。经过几个小时的挫折后,我终于在几个月前解决了这个问题......
我发现它是由副本集故障转移触发的。这是通过在Azure上使用测试服务器并在MongoLab上设置测试副本以及在Mongolab上手动触发故障转移来验证的(我无法通过在本地运行NodeJs服务器和MongoDB实例来重现,因为问题与连接时间有关)。 / p>
故障转移后应该帮助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);
})
}
答案 2 :(得分:0)
根据我的经验,我建议您可以在Mlab上ping mongodb,以确保在您的webapp挂起时是否用完了mongo连接。
我认为你可以尝试为mongoose连接添加连接池选项,正如@BlakesSeven所说。请参阅Mongoose guide topic Connections
的Connection pools
部分以配置池大小。