node.js 猫鼬自动重新连接选项

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16226472/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 14:19:25  来源:igfitidea点击:

Mongoose autoReconnect option

node.jsmongodbmongoose

提问by gustavohenke

I'm trying to set up the MongoDB auto reconnection feature via Mongoose. Every way that I have tried to pass the option has had no effect, or at least the reconnectedevent isn't being emitted.

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

What I've tried:

我试过的:

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

If one of these is correct, the reconnectedevent should be triggered and a message should be logged in the console, however this never happens.

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

If there is a delay before the reconnection, does anyone know how to configure it?

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

Thanks in advance

提前致谢

For anyone looking into this, take a look at thisand thisissue in mongoose repository.

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

回答by Zebra Propulsion Lab

I had the same question as you, and robertklep's solution didn't work for me either. I found when MongoDB service is stopped, an error event is triggered, but the connection.readyState is still 1 (connected). That may be why it didn't auto reconnect.

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

This is what I have now:

这就是我现在所拥有的:

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

回答by Ricky

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

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

This worked for me:

这对我有用:

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

回答by zangw

Recently, I investigate the auto-reconnect with MongoDBvar Mongoose. There is one issue here, when invoking mongoose.connectwithin disconnectedevent handler, it will trigger infinite loop. Why the SIGINT signal is blocked when mongoose auto reconnect.

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

One work around solution could be that the mongoose.connect()only be called when there is no connection with MongoDBbefore. The auto_reconnectflag could make mongoose reconnect with MongoDBautomatically. Here are code snippets.

一种变通的解决方案可能是mongoose.connect()只有在与MongoDB之前没有联系时才调用。该auto_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);
    });
});

回答by joniba

Just for the sake of posterity, as most of these answers are old, you should not need to deal with this issue any more, as it is now baked into the nodejs mongodb driver. To quote kdmon:

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

...reconnecting is now baked into mongoose and enabled by default. But it might be useful to know that Mongoose by default will only try reconnecting for 30s and then give up. Set the server.reconnectTries option to increase the number of times mongoose will try to reconnect. For example, you can tell mongoose to never stop trying to reconnect like this:

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

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

See connection docsand server optionsdefaults for details

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

回答by zurfyx

@Clive's answerwas excellent. Nonetheless, due to using mongoosewith PromiseI was getting the following warning after every failed attempt:

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

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

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

ES6 version (with Promise)

ES6 版本(带 Promise)

I also added a small timeout between reconnects in this version (completely optional), to prevent your screen (or your logger) being flooded of repeated messages.

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

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

Further information on Connectionevents.

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

回答by Gil SH

Here is an improvement to Clive's answer that sets a minimum of 5 seconds between connection attempts.

这是对 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}});
    }

});

回答by mattwad

Make sure mongoose is also the only way you're connecting to Mongo. In my case, I am using connect-mongoto store sessions in Express, but it does not have auto_reconnect set to true by default, as of v0.4.0.

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

回答by Dr.Knowitall

After reading the docs, I'm pretty sure you have the options wrong. The connection options string should look like:

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

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

Check this page out: http://mongoosejs.com/docs/api.html

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

回答by Alendorff

Based on @zangw answer, I've finished with this database init function for my app

基于@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)
    })
  })
}

There is a few differences: I've added some options to prevent connection closing issue - no reconnect after 30 auto retries, just MongoError: Topology was destroyed for any operation and no reconnect; also I've added .catch after connect to prevent unhandled promise rejection):

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

回答by jonasnas

To have multiple retries without request blocking while retrying I had to set bufferMaxEntries: 0:

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