【问题标题】:Mongoose autoReconnect option猫鼬自动重新连接选项
【发布时间】:2013-04-20 00:56:55
【问题描述】:

我正在尝试通过 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 存储库中的 this 和 this 问题。

【问题讨论】:

  • 自动重连默认是开启的,所以你不必自己开启。另外,您将reconnected 事件的侦听器附加到什么上,您是否在模拟实际的重新连接情况?
  • 我将该事件附加到此createConnection() 调用的返回中。我的事件与connected/disconnected 事件一起正常工作。
  • 那么您如何测试重新连接?
  • 应用初始化后停止/启动mongodb服务。
  • mongoose 只会在你实际使用连接时重新连接,所以在重启 mongodb 后尝试运行查询。我正在以这种方式重新连接事件(尽管我使用 mongoose.connect() 而不是 createConnection(),也许这会有所不同)

标签: node.js mongodb mongoose


【解决方案1】:

我和你有同样的问题,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}});

【讨论】:

  • 在断开连接时重新连接是非常错误的。相反,您应该监控错误并从那里重新连接
  • Mongoose 出错时不会断开连接,所以我必须明确断开它才能重新连接
  • 对于那些有兴趣阅读官方猫鼬Connection docs的人。 mongoosejs.com/docs/3.0.x/docs/api.html#connection_Connection
  • {server:{auto_reconnect:true}} 位是否会导致猫鼬在您断开连接时自动重新连接?例如,如果error 事件被触发并且您断开连接,猫鼬会为您重新连接吗?如果不是,您为什么不想尝试重新连接,因为我认为这可能是一些微不足道的通信错误?或者在这种情况下您的“断开连接”事件是否会被触发,并处理重新连接?如果是这样,auto_reconnect 还在做什么?你没有重新实现它吗?
  • 这种方法给我带来了各种错误,对我不起作用
【解决方案2】:

取自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();

【讨论】:

  • 最佳选择!
【解决方案3】:

最近,我使用MongoDB var Mongoose 调查自动重新连接。这里有一个问题,当在disconnected 事件处理程序中调用mongoose.connect 时,会触发无限循环。 Why the SIGINT signal is blocked when mongoose auto reconnect.

一种变通解决方案可能是仅在之前与MongoDB 没有连接时才调用mongoose.connect()。 auto_reconnect 标志可以使 mongoose 自动与 MongoDB 重新连接。这是代码sn-ps。

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

【讨论】:

  • 对我来说这是最好的答案。无限循环是我的问题。谢谢老兄
【解决方案4】:

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

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

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

有关详细信息,请参阅 connection docs 和 server options 默认值

【讨论】:

  • 使用这个标志的问题是它把猫鼬调用变成了阻塞调用,即它们在数据库再次启动之前不会返回。在我的例子中,我从一个 express 应用程序中调用了 mongoose,我们更愿意返回一个错误而不是阻止请求。
  • 我希望这是真的。如果连接在运行期间丢失,则为 true。但是如果 first 连接尝试失败(因为 mongo DB 已关闭),驱动程序将永远不会重试。
【解决方案5】:

@Clive 的answer 非常棒。尽管如此,由于将mongoose 与Promise 一起使用,我在每次尝试失败后都会收到以下警告:

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

有关Connection 事件的更多信息。

【讨论】:

    【解决方案6】:

    这是对 Clive 答案的改进,它在连接尝试之间设置了至少 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}});
        }
    
    });
    

    【讨论】:

    • 你为什么要用auto_reconnect: true,不应该是false,如果你手动重连为什么要设置auto_reconnect为true?
    • auto_reconnect: true 只有在第一次连接成功时才能按预期工作。由于某种原因,如果第一次连接失败,驱动程序就再也没有尝试过。因此,您可以在此处找到所有这些解决方法。也就是说,我认为您可以忽略该选项,因为它默认为 true。
    • 我最终使用了类似的东西,除了我将重试移动到一个独立的函数中,因此如果初始连接失败,它也可以在初始时调用。
    【解决方案7】:

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

    【讨论】:

      【解决方案8】:

      根据@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 以防止未处理的承诺拒绝):

      【讨论】:

        【解决方案9】:

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

        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

        【讨论】:

        • 随着时间的推移,这些选项发生了变化。这个问题是 4 年前创建的。
        【解决方案10】:

        要在重试时多次重试而不阻塞请求,我必须设置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));
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2016-11-26
          • 1970-01-01
          • 2021-12-04
          • 2015-04-01
          • 2016-04-13
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多