如何确保Node.js在MonogDB连接断开后继续运行?

如何确保Node.js在MonogDB连接断开后继续运行?,node.js,mongodb,error-handling,express,mongoose,Node.js,Mongodb,Error Handling,Express,Mongoose,我在Express中处理middlware时出错,试图捕获所有传入错误: app.use(function(err, req, res, next){ console.error(err.stack); res.status(500); res.render('500.jade'); }); 但由于某种原因,每当我关闭mongod进程时,我的应用程序就会崩溃,并出现以下堆栈跟踪: Error: failed to connect to [localhost:27017] a

我在Express中处理middlware时出错,试图捕获所有传入错误:

app.use(function(err, req, res, next){
  console.error(err.stack);
  res.status(500);
  res.render('500.jade');
});
但由于某种原因,每当我关闭
mongod
进程时,我的应用程序就会崩溃,并出现以下堆栈跟踪:

Error: failed to connect to [localhost:27017]
    at null.<anonymous> (/<hidden>/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/server.js:540:74)
    at EventEmitter.emit (events.js:106:17)
    at null.<anonymous> (/<hidden>/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/connection_pool.js:140:15)
    at EventEmitter.emit (events.js:98:17)
    at Socket.<anonymous> (/<hidden>/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/connection.js:478:10)
    at Socket.EventEmitter.emit (events.js:95:17)
    at net.js:441:14
    at process._tickCallback (node.js:415:13)

Process finished with exit code 8
有人可能会问:“如果没有数据库连接,应用程序基本上不再运行,为什么您希望应用程序运行?”。我不希望它崩溃并重新启动。经过一定次数的尝试后,Supervisor和Forever模块似乎停止尝试重新连接,从而使应用程序处于崩溃状态

理想情况下,当MongoDB崩溃时,我希望向用户显示一个500.jade错误页面,同时服务器应每10秒尝试重新连接到数据库。重新连接后,恢复所有正常操作。


编辑:除了域之外,下面发布的所有解决方案都不适合我

尝试在中初始化数据库,这样可以在不崩溃的情况下捕获错误

var d = require('domain').create();

d.on('error', function(er) {
    console.log('Oh no, something wrong with DB');
});

d.run(function() {
    mongoose.connect(config.db, options);
});

通常情况下,让服务器在崩溃时重新启动是一个好主意,但您已经意识到这一点,并且希望避免它,因此,将域中出现的任何故障包装起来是一种方法。

当连接丢失时,MongoDB驱动程序会发出一个“关闭”事件。您可以点击此事件并将DB标记为不可用,并基于此写入任何逻辑

db.on('close', function() {
  // handle the disconnect
  dbAvailable = false;
});

如果您有兴趣,我有一个小的NPM模块来处理这个问题:

这就是我处理Mongo失败的方法-将其添加为中间件。它还将再次尝试重新连接

// Handler in case Mongo  goes down
app.use(function(req, res, next) {
  // We lost connection!
  if (1 !== mongoose.connection.readyState) {

    // Reconnect if we can
    mongoose.connect(config.db, options);
    res.status(503);
    throw new Error('Mongo not available');
  }
  next();

});
这假设您在某个地方有一个标准的50x错误处理程序,可以向用户显示一个漂亮的页面


重新连接用于下一个用户/页面加载,以检查其是否已备份。很好用。

太棒了,我以前从未使用过Node.js域。今天学到了新东西;)。漂亮而优雅的解决方案。@TwilightPonyInc.-不久前添加到的域,仍然被认为有点不稳定,但我在生产中使用类似于Cassandra的东西作为DB已经有一段时间了,而且从来没有出现过问题,如果DB失败节点继续运行,当DB再次可用时,就好像什么都没有发生过一样,我到处寻找漏洞,对我来说似乎很好。我还没有在Mongo上真正尝试过,但原则上应该是一样的。只是不要开始在域中包装内部节点进程,因为这实际上可能会导致问题和严重的泄漏。我不建议域中包含任何Mongoose内容-您必须将所有查询都包装在其中。正在等待Mongoose支持。不会对域中的任何数据库或任何其他内容提供特殊支持,因为域只是捕获任何错误的一种方式,甚至是致命的节点错误,而不会导致节点崩溃。因此,应谨慎使用域,因为如果节点未重新启动,某些错误可能会导致意外行为。一般来说,数据库错误在节点中并不是致命的,根据我的经验,如果节点不重新启动,也不会导致问题,因此,它们是为什么一开始就添加域的完美例子;包装可能失败的代码,以便在失败期间不会使整个节点进程崩溃。我可以通过执行一个简单的
console.log()
来成功捕获此事件,但大约1秒后,服务器会使用
thrower;//崩溃未处理的“错误”事件
。我做错什么了吗?(使用最新版本的Express和Mongoose)。类似:
// Handler in case Mongo  goes down
app.use(function(req, res, next) {
  // We lost connection!
  if (1 !== mongoose.connection.readyState) {

    // Reconnect if we can
    mongoose.connect(config.db, options);
    res.status(503);
    throw new Error('Mongo not available');
  }
  next();

});