Mongoose autoReconnect选项

时间:2013-04-25 23:40:47

标签: node.js mongodb mongoose

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

10 个答案:

答案 0 :(得分:50)

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

答案 1 :(得分:14)

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

答案 2 :(得分:11)

最近,我调查了与MongoDB var Mongoose的自动重新连接。这里有一个问题,当在mongoose.connect事件处理程序中调用disconnected时,它将触发无限循环。 Why the SIGINT signal is blocked when 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);
    });
});

答案 3 :(得分:8)

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

  

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

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

有关详细信息,请参阅connection docsserver options默认值

答案 4 :(得分:3)

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

答案 5 :(得分:3)

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

});

答案 6 :(得分:3)

@ Clive的answer非常出色。尽管如此,由于mongoosePromise一起使用,每次尝试失败后都会收到以下警告:

  

(node:18123)UnhandledPromiseRejectionWarning:未处理的promise promise(拒绝ID:1):MongoError:第一次连接时无法连接到服务器[localhost:27017]

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事件的更多信息。

答案 7 :(得分:1)

阅读完文档后,我很确定你选错了。连接选项字符串应如下所示:

    vec4 tmp = vec4(a_position,1.0);
    tmp = uMVMat * tmp; //Applying the ModelView Matrix
    float r2 = dot(tmp.xy,tmp.xy); //Calculating the squared radius
    tmp.xy *= 1.0f + (-0.55+0.34*r2)*r2; //Applying the Formula to x and y

    gl_Position = uPMat * tmp;

查看此页面:Int32.Equals(Int32)

答案 8 :(得分: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));

答案 9 :(得分:0)

根据@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:拓扑被破坏以进行任何操作而没有重新连接;我也在连接后添加了.catch以防止未处理的承诺拒绝):