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
Mongoose autoReconnect option
提问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.
回答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.connect在disconnected事件处理程序中调用时,会触发无限循环。为什么 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
回答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));

