mongoDB有重新连接的问题,或者我做错了吗?

我正在使用nodejs和一个mongoDB – 我有一些连接问题。

那么,实际上是“唤醒”问题! 它连接得非常好 – 速度超快,我对结果一般感到满意。

我的问题:如果我不使用连接一段时间(我说,而时间框架变化5+分钟)似乎失速。 我没有被解雇的事件 – 它只是挂起。

最后我得到一个响应,如错误:无法连接到[* .mongolab.com:*] – (* =屏蔽值)

该应用程序的快速重新启动,连接再次伟大。 有时,如果我不重新启动应用程序,我可以刷新并重新连接。

这就是为什么我认为这是“醒来”的问题。

代码的粗略轮廓:

我没有包括代码 – 我不认为这是必要的。 它工作(除了连接丢失)

注意事项:只有一个“连接” – 我从来没有closures它。 我从来没有重新开放。

我正在使用mongoose,socketio。

/* constants */ var mongoConnect = 'myworkingconnectionstring-includingDBname'; /* includes */ /* settings */ /* Schema */ var db = mongoose.connect(mongoConnect); /* Socketio */ io.configure(function (){ io.set('authorization', function (handshakeData, callback) { }); }); io.sockets.on('connection', function (socket) { });//sockets io.sockets.on('disconnect', function(socket) { console.log('socket disconnection') }); /* The Routing */ app.post('/login', function(req, res){ }); app.get('/invited', function(req, res){ }); app.get('/', function(req, res){ }); app.get('/logout', function(req, res){ }); app.get('/error', function(req, res){ }); server.listen(port); console.log('Listening on port '+port); db.connection.on('error', function(err) { console.log("DB connection Error: "+err); }); db.connection.on('open', function() { console.log("DB connected"); }); db.connection.on('close', function(str) { console.log("DB disconnected: "+str); }); 

我在这里尝试过各种configuration,比如总是打开和closures – 我相信虽然一般的共识就是这样做,因为我一开口就包装了很多东西。 ??

我试了一个连接testing仪,不断检查连接的状态…即使这似乎说everthing的确定 – 问题仍然发生。

我从一开始就有这个问题。 我一直使用MongoLab托pipeMongoDB。 本地主机上的问题似乎更糟糕。 但我仍然有问题在Azure上,现在nodejit.su。

随处可见 – 它一定是我,MongoDB或者mongolab。

顺便说一下,我也有类似的经验与PHP的驱动程序。 (虽然确认这是在nodejs上)

这将是伟大的一些帮助 – 即使有人只是说“这是正常的”

提前致谢

更新 :我们这个主题的支持文章(本质上是这篇文章的副本)已经转移到我们的连接故障诊断文档 。

有一个已知的问题,即Azure IaaSnetworking强制执行大约十三分钟的空闲超时(凭经验到达)。 我们正在与Azure合作,看看我们是不是可以使用户更友好,但是与此同时,其他人通过configuration驱动程序选项来解决这个问题已经取得了成功。

最大连接空闲时间

我们在与Azure和我们的客户合作时发现的最有效的解决方法是将最大连接空闲时间设置为低于四分钟。 这个想法是在防火墙强制解决问题之前让驱动程序回收空闲连接。 例如,一位使用C#驱动程序的客户将MongoDefaults.MaxConnectionIdleTime设置为一分钟,并清除了问题。

 MongoDefaults.MaxConnectionIdleTime = TimeSpan.FromMinutes(1); 

应用程序代码本身没有改变,但现在在后台司机积极回收空闲连接。 结果也可以在服务器日志中看到:在应用程序闲置期间,大量的连接stream失。

有关这种方法的更多细节在相关的mongo用户线程中, 使用Azure上的C#驱动程序的SocketException 。

活着

你也可以通过让你的连接less一些keepalive来解决这个问题。 除非您的驱动程序支持开箱即用,这通常是通过利用TCP Keepalive来实现的 。 如果你需要推出自己的游戏,请确保每隔几分钟从游泳池中抓取每个空闲的连接,并发出一些简单而便宜的命令,可能是ping 。

处理断开连接

即使没有积极的防火墙设置,断开连接也会时有发生。 在进入生产之前,您要确保正确处理它们。

首先,一定要启用自动重新连接。 操作方法因驱动程序而异,但是当驱动程序检测到由于连接不良而导致操作失败时,打开自动重新连接会告诉驱动程序尝试重新连接。

但是这并不能完全解决问题。 您仍然遇到触发重新连接的失败操作的问题。 自动重新连接不会自动重试失败的操作。 这将是危险的,特别是写作。 所以通常会抛出exception,并要求应用程序处理它。 通常重试读取是一件容易的事情。 但是应该仔细考虑重试写入。

下面的mongo shell会话演示了这个问题。 mongo shell默认启用了自动重新连接。 我在一个名为stuff的集合中插入一个文档,然后find该集合中的所有文档。 然后,我设置一个计时器三十分钟,然后再次尝试相同的查找。 它失败了,但shell自动重新连接,当我立即重试我发现它按预期工作。

 % mongo ds012345.mongolab.com:12345/mydatabase -u *** -p *** MongoDB shell version: 2.2.2 connecting to: ds012345.mongolab.com:12345/mydatabase > db.stuff.insert({}) > db.stuff.find() { "_id" : ObjectId("50f9b77c27b2e67041fd2245") } > db.stuff.find() Fri Jan 18 13:29:28 Socket recv() errno:60 Operation timed out 192.168.1.111:12345 Fri Jan 18 13:29:28 SocketException: remote: 192.168.1.111:12345 error: 9001 socket exception [1] server [192.168.1.111:12345] Fri Jan 18 13:29:28 DBClientCursor::init call() failed Fri Jan 18 13:29:28 query failed : mydatabase.stuff {} to: ds012345.mongolab.com:12345 Error: error doing query: failed Fri Jan 18 13:29:28 trying reconnect to ds012345.mongolab.com:12345 Fri Jan 18 13:29:28 reconnect ds012345.mongolab.com:12345 ok > db.stuff.find() { "_id" : ObjectId("50f9b77c27b2e67041fd2245") } 

我们在这里帮助

当然,如果您有任何问题,请随时通过support@mongolab.com与我们联系。 我们在这里帮助。

感谢所有帮助的人 – 我已经设法解决这个问题在两个本地主机和部署到一个活的服务器。

这是我现在工作的连接代码:

 var MONGO = { username: "username", password: "pa55W0rd!", server: '******.mongolab.com', port: '*****', db: 'dbname', connectionString: function(){ return 'mongodb://'+this.username+':'+this.password+'@'+this.server+':'+this.port+'/'+this.db; }, options: { server:{ auto_reconnect: true, socketOptions:{ connectTimeoutMS:3600000, keepAlive:3600000, socketTimeoutMS:3600000 } } } }; var db = mongoose.createConnection(MONGO.connectionString(), MONGO.options); db.on('error', function(err) { console.log("DB connection Error: "+err); }); db.on('open', function() { console.log("DB connected"); }); db.on('close', function(str) { console.log("DB disconnected: "+str); }); 

我认为最大的变化是在“连接”上使用“createConnection” – 之前我曾经使用过这个function,但现在可能还是有帮助的。 这篇文章帮助了很多http://journal.michaelahlers.org/2012/12/building-with-nodejs-persistence.html

如果我是诚实的,我不太清楚为什么我添加了这些选项 – 正如@jareed所说的,我还发现一些人用“MaxConnectionIdleTime”取得了成功 – 但是据我所见,JavaScript的驱动程序不有这个选项:这是我试图复制的行为。

到目前为止这么好 – 希望这有助于某人。

更新:2013年4月18日 请注意,这是一个不同的设置的第二个应用程序

现在我想我已经解决了这个问题,但是最近又出现了另一个应用程序的问题 – 使用相同的连接代码。 困惑!!!

不过设置稍有不同…

这个新的应用程序运行在使用IISNode的窗口框。 我最初并没有看到这一点。

我读过有关Azure(@jareed)上的mongo可能存在的一些问题,所以我将数据库移到了AWS上 – 仍然存在问题。

所以我又开始玩这个选项对象,读了很多。 得出这个结论:

 options: { server:{ auto_reconnect: true, poolSize: 10, socketOptions:{ keepAlive: 1 } }, db: { numberOfRetries: 10, retryMiliSeconds: 1000 } } 

这是一个更多的教育,我的原始选项对象我声明。 但是 – 这仍然不好。

现在,由于某种原因,我不得不离开那个窗口框(与不编译的模块有关) – 移动比再花一周的时间更容易。

所以我把我的应用程序移动到nodejitsu。 低,看看我的联系活着! 呜!

所以…。 这是什么意思…我不知道! 我所知道的是这些选项似乎在Nodejitsu上工作…。 为了我。

我相信IISNode使用某种“永远”的脚本来保持应用程序的活着。 现在公平地说,应用程序不会因此而崩溃,但我认为必须有一种不断刷新的“应用程序周期” – 这是如何进行连续部署(ftp代码,不需要重新启动应用程序) – 也许这是一个因素; 但我现在只是猜测。

当然这一切意味着现在,这是不解决的。 这仍然没有解决。 这只是在我的设置中解决了。

对于仍然存在这个问题的人们有一些build议:

  1. 确保您使用最新的mongodb客户端用于node.js. 从v1.2.x迁移到v1.3.10(今天是最新版本),我注意到了这方面的重大改进,

  2. 您可以将选项对象传递给MongoClient.connect。 从Azure连接到MongoLab时,以下选项适用于我:

    options = {db:{},server:{auto_reconnect:true,socketOptions:{keepAlive:1}},replSet:{},mongos:{}};

    MongoClient.connect(dbUrl,options,function(err,dbConn){// your code});

  3. 看到这个其他答案,我描述了如何处理似乎更可靠的“closures”事件。 https://stackoverflow.com/a/20690008/446681

像这样启用auto_reconnect Server选项:

 var db = mongoose.connect(mongoConnect, {server: {auto_reconnect: true}}); 

你在这里打开的连接实际上是一个由5个连接组成的连接池(默认情况下),所以你只需连接并保持打开即可。 我的猜测是,你间歇性地失去了与蒙哥拉的连接,并且当这种情况发生时,你的连接就会死亡。 希望启用auto_reconnect可以解决这个问题。

增加超时可能会有所帮助。

  • “socketTimeoutMS”:在超时之前,套接字上的发送或接收可能需要多长时间。
  • “wTimeoutMS”:它控制服务器等待写入关心满足的毫秒数。
  • “connectTimeoutMS”:连接在超时之前可以打开多长时间,以毫秒为单位。

    $ m = new MongoClient(“mongodb://127.0.0.1:27017”,array(“connect”=> TRUE,“connectTimeoutMS”=> 10,“socketTimeoutMS”=> 10,“wTimeoutMS”=> 10));

      $db= $m->mydb; $coll = $db->testData; $coll->insert($paramArr); 

我有一个类似的问题定期从MongoDB断开连接 。 做两件事固定它:

  1. 确保你的电脑不睡觉(这会杀死你的networking连接)。
  2. 绕过你的路由器/防火墙(或正确configuration,我还没有想出如何做)。