33

我正在尝试通过 Mongoose 设置 MongoDB 自动重新连接功能。我尝试通过该选项的每种方式都没有效果,或者至少reconnected没有发出事件。

我试过的:

mongoose.createConnection("mongodb://localhost:27017/test", { auto_reconnect: true });
mongoose.createConnection("mongodb://localhost:27017/test", { autoReconnect: true });
mongoose.createConnection("mongodb://localhost:27017/test", { server: { auto_reconnect: true } });
mongoose.createConnection("mongodb://localhost:27017/test", { server: { autoReconnect: true } });

如果其中一个是正确的,则reconnected应该触发该事件并且应该在控制台中记录一条消息,但是这永远不会发生。

如果在重新连接之前有延迟,有谁知道如何配置它?

提前致谢

对于任何研究此问题的人,请查看 mongoose 存储库中的问题和问题。

4

10 回答 10

62

我和你有同样的问题,robertklep 的解决方案也对我不起作用。我发现当MongoDB服务停止时,触发了一个错误事件,但是connection.readyState仍然是1(已连接)。这可能是它没有自动重新连接的原因。

这就是我现在所拥有的:

  var db = mongoose.connection;

  db.on('connecting', function() {
    console.log('connecting to MongoDB...');
  });

  db.on('error', function(error) {
    console.error('Error in MongoDb connection: ' + error);
    mongoose.disconnect();
  });
  db.on('connected', function() {
    console.log('MongoDB connected!');
  });
  db.once('open', function() {
    console.log('MongoDB connection opened!');
  });
  db.on('reconnected', function () {
    console.log('MongoDB reconnected!');
  });
  db.on('disconnected', function() {
    console.log('MongoDB disconnected!');
    mongoose.connect(dbURI, {server:{auto_reconnect:true}});
  });
  mongoose.connect(dbURI, {server:{auto_reconnect:true}});
于 2013-06-13T17:33:45.180 回答
18

摘自http://bites.goodeggs.com/posts/reconnecting-to-mongodb-when-mongoose-connect-fails-at-startup/

这对我有用:

var mongoose = require('mongoose')
var mongoUrl = "mongodb://localhost:27017/test"

var connectWithRetry = function() {
  return mongoose.connect(mongoUrl, function(err) {
    if (err) {
      console.error('Failed to connect to mongo on startup - retrying in 5 sec', err);
      setTimeout(connectWithRetry, 5000);
    }
  });
};
connectWithRetry();
于 2014-10-02T16:02:49.577 回答
15

MongoDB最近,我研究了var的自动重新连接Mongoose。这里有一个问题,mongoose.connectdisconnected事件处理程序中调用时,它会触发无限循环。为什么 SIGINT 信号在 mongoose auto reconnect 时被阻塞

一种解决方法可能是唯一在与之前mongoose.connect()没有连接时调用的方法。MongoDBauto_reconnect标志可以使猫鼬MongoDB自动重新连接。这是代码片段。

var mongoose = require('mongoose');

var isConnectedBefore = false;
var connect = function() {
    mongoose.connect('mongodb://localhost/' + + 'test_dev', {server: { auto_reconnect: true }});
};
connect();

mongoose.connection.on('error', function() {
    console.log('Could not connect to MongoDB');
});

mongoose.connection.on('disconnected', function(){
    console.log('Lost MongoDB connection...');
    if (!isConnectedBefore)
        connect();
});
mongoose.connection.on('connected', function() {
    isConnectedBefore = true;
    console.log('Connection established to MongoDB');
});

mongoose.connection.on('reconnected', function() {
    console.log('Reconnected to MongoDB');
});

// Close the Mongoose connection, when receiving SIGINT
process.on('SIGINT', function() {
    mongoose.connection.close(function () {
        console.log('Force to close the MongoDB conection');
        process.exit(0);
    });
});
于 2015-11-09T06:29:37.007 回答
12

只是为了子孙后代,由于这些答案中的大多数都是旧的,您应该不再需要处理这个问题,因为它现在已被嵌入到 nodejs mongodb 驱动程序中。引用kdmon

...重新连接现在被烘焙到猫鼬中并默认启用。但是知道默认情况下 Mongoose 只会尝试重新连接 30 秒然后放弃可能很有用。设置 server.reconnectTries 选项以增加 mongoose 尝试重新连接的次数。例如,您可以告诉 mongoose 永远不要停止尝试重新连接,如下所示:

mongoose.connect(uri, { server: { reconnectTries: Number.MAX_VALUE } });

有关详细信息,请参阅连接文档服务器选项默认值

于 2016-09-25T08:11:26.650 回答
7

@Clive 的回答非常好。尽管如此,由于使用mongoosewithPromise我在每次尝试失败后都会收到以下警告:

(node:18123) UnhandledPromiseRejectionWarning: UnhandledPromiseRejectionWarning: Unhandled Promise Rejection (rejection id: 1): MongoError: failed to connect to server [localhost:27017] on first connect

ES6 版本(含 Promise)

在此版本中,我还在重新连接之间添加了一个小超时(完全可选),以防止您的屏幕(或您的记录器)被重复消息淹没。

import mongoose from 'mongoose';

mongoose.Promise = Promise; // Set mongoose to use ES6 Promises.

const dbURI = 'mongodb://127.0.0.1:27017/myDb';
const reconnectTimeout = 5000; // ms.

function connect() {
  mongoose.connect(dbURI, { auto_reconnect: true })
    .catch(() => {}); // Catch the warning, no further treatment is required
                      // because the Connection events are already doing this
                      // for us.
}

const db = mongoose.connection;

db.on('connecting', () => {
  console.info('Connecting to MongoDB...');
});

db.on('error', (error) => {
  console.error(`MongoDB connection error: ${error}`);
  mongoose.disconnect();
});

db.on('connected', () => {
  console.info('Connected to MongoDB!');
});

db.once('open', () => {
  console.info('MongoDB connection opened!');
});

db.on('reconnected', () => {
  console.info('MongoDB reconnected!');
});

db.on('disconnected', () => {
  console.error(`MongoDB disconnected! Reconnecting in ${reconnectTimeout / 1000}s...`);
  setTimeout(() => connect(), reconnectTimeout);
});

connect();

有关连接事件的更多信息。

于 2017-01-25T19:25:56.937 回答
4

这是对克莱夫答案的改进,它在连接尝试之间设置了至少 5 秒。

var db = mongoose.connection;
var lastReconnectAttempt; //saves the timestamp of the last reconnect attempt
db.on('error', function(error) {
    console.error('Error in MongoDb connection: ' + error);
    mongoose.disconnect();
});
db.on('disconnected', function() {
    console.log('MongoDB disconnected!');
    var now = new Date().getTime();
    // check if the last reconnection attempt was too early
    if (lastReconnectAttempt && now-lastReconnectAttempt<5000) {
        // if it does, delay the next attempt
        var delay = 5000-(now-lastReconnectAttempt);
        console.log('reconnecting to MongoDB in ' + delay + "mills");
        setTimeout(function() {
            console.log('reconnecting to MongoDB');
            lastReconnectAttempt=new Date().getTime();
            mongoose.connect(dbURI, {server:{auto_reconnect:true}});
        },delay);
    }
    else {
        console.log('reconnecting to MongoDB');
        lastReconnectAttempt=now;
        mongoose.connect(dbURI, {server:{auto_reconnect:true}});
    }

});
于 2015-10-15T04:02:01.617 回答
3

确保猫鼬也是您连接到 Mongo 的唯一方式。就我而言,我使用connect-mongo在 Express 中存储会话,但从 v0.4.0 开始,默认情况下它没有将 auto_reconnect 设置为 true。

于 2014-05-04T18:12:01.760 回答
2

基于@zangw 的回答,我已经为我的应用程序完成了这个数据库初始化函数

const mongoose = require('mongoose')
const RETRY_TIMEOUT = 3000

module.exports = function initDB () {
  mongoose.Promise = global.Promise
  const options = {
    autoReconnect: true,
    useMongoClient: true,
    keepAlive: 30000,
    reconnectInterval: RETRY_TIMEOUT,
    reconnectTries: 10000
  }

  let isConnectedBefore = false

  const connect = function () {
    return mongoose.connect(process.env.MONGODB_URL, options)
      .catch(err => console.error('Mongoose connect(...) failed with err: ', err))
  }

  connect()

  mongoose.connection.on('error', function () {
    console.error('Could not connect to MongoDB')
  })

  mongoose.connection.on('disconnected', function () {
    console.error('Lost MongoDB connection...')
    if (!isConnectedBefore) {
      setTimeout(() => connect(), RETRY_TIMEOUT)
    }
  })
  mongoose.connection.on('connected', function () {
    isConnectedBefore = true
    console.info('Connection established to MongoDB')
  })

  mongoose.connection.on('reconnected', function () {
    console.info('Reconnected to MongoDB')
  })

  // Close the Mongoose connection, when receiving SIGINT
  process.on('SIGINT', function () {
    mongoose.connection.close(function () {
      console.warn('Force to close the MongoDB connection after SIGINT')
      process.exit(0)
    })
  })
}

有一些区别:我添加了一些选项来防止连接关闭问题 - 自动重试 30 次后没有重新连接,只是 MongoError: Topology was destroy for any operation and no reconnect; 我还在连接后添加了 .catch 以防止未处理的承诺拒绝):

于 2017-08-23T11:07:41.147 回答
1

阅读文档后,我很确定您的选项有误。连接选项字符串应如下所示:

mongoose.connect("mongodb://localhost:27017/db", {
    socketOptions: {
      // This option is on by default, but why not set it explicitly
      autoReconnect: true
    },
    // This options is 1 second by default, its possible the ha
    // takes longer than 30 seconds to recover.
    reconnectInterval: 5000,
    // This options is 30 by default, why not make it 60
    reconnectTries: 60
  })

查看此页面: http: //mongoosejs.com/docs/api.html

于 2017-01-29T17:23:57.417 回答
1

要在重试时多次重试而不阻塞请求,我必须设置bufferMaxEntries: 0

const dbUri = 'mongodb://localhost/some_db';
const dbOptions = {
    useMongoClient: true,
    autoReconnect: true,
    reconnectTries: Number.MAX_VALUE,
    bufferMaxEntries: 0
};

mongoose.connect(dbUri, dbOptions).catch(err => process.exit(1));
于 2017-11-17T11:39:11.703 回答