2013-04-25 2 views
20

Я пытаюсь настроить функцию автоматического пересоединения MongoDB через Mongoose. Каждый способ, которым я пытался передать этот вариант, не имел никакого эффекта, или, по крайней мере, событие reconnected не выдается.Mongoose autoReconnect опция

Что я пробовал:

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 событие должно быть инициировано и сообщение должно быть зарегистрировано в консоли, но это никогда не происходит.

Если есть задержка перед повторным подключением, кто-нибудь знает, как ее настроить?

Заранее спасибо

Для тех, кто ищет в этом, посмотрите на this и this выпуска в хранилище мангустов.

+0

Autoreconnect включен по умолчанию, так что вы не не нужно включать его самостоятельно. Кроме того, к чему вы присоединяете слушателя к событию «вновь подключенного» и имитируете реальную ситуацию повторного подключения? – robertklep

+0

Я присоединяю это событие к возврату этого вызова 'createConnection()'. Мои события работают нормально с событиями 'connected' /' disconnected'. – gustavohenke

+0

Итак, как вы тестируете пересоединения? – robertklep

ответ

38

У меня был тот же вопрос, что и вы, и решение 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

Неправильно подключаться к разъединению. Вместо этого вы должны отслеживать ошибку и повторно подключаться оттуда – Andy

+4

Mongoose не отключается при ошибке, поэтому я должен явно отключить его, чтобы повторно подключить –

+0

Для тех, кто заинтересован в чтении ** официальных документов mongoose 'Connection' docs **. http://mongoosejs.com/docs/3.0.x/docs/api.html#connection_Connection – zurfyx

3

Убедитесь мангуст является единственным способом вы подключаетесь к Монго. В моем случае я использую connect-mongo для хранения сеансов в Express, но по умолчанию у него нет auto_reconnect, установленного по умолчанию, начиная с версии v0.4.0.

10

Полушубок из 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(); 
+0

Это работает для меня! –

1

Вот улучшение ответа Клайва, который устанавливает минимум 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}}); 
    } 

}); 
+2

Почему вы используете 'auto_reconnect: true', не должно быть' false', если вы повторно подключаетесь вручную, почему вам нужно установить 'auto_reconnect' в' true'? –

+0

'auto_reconnect: true' работает только в том случае, если первое соединение выполнено успешно. По какой-то причине, если первое соединение не удалось, драйвер никогда не пытался снова. Следовательно, все эти обходные пути вы найдете здесь. Тем не менее, я думаю, вы можете оставить опцию, так как по умолчанию она по-прежнему истинна. – joeytwiddle

9

Недавно я исследую автоматический воссоединиться с MongoDB варом Mongoose. Здесь есть одна проблема: при вызове mongoose.connect в обработчике события disconnected он вызовет бесконечный цикл. Why the SIGINT signal is blocked when mongoose auto reconnect.

Одно решение для работы может заключаться в том, что 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); 
    }); 
}); 
+0

Для меня это лучший ответ. Бесконечный цикл был моей проблемой. Спасибо dude – emilioriosvz

4

Просто ради потомства, так как большинство из этих ответов старо, вы не должны иметь дело с этим вопросом больше, как теперь запеченный в 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.connect(uri, { server: { reconnectTries: Number.MAX_VALUE } }); 

See connection docs and server options defaults for details

+0

Проблема с использованием этого флага заключается в том, что он превращает вызовы мангуста в блокирующие вызовы, т. Е. Они не возвращаются, пока база данных не будет снова. В моем случае я вызывал mongoose из экспресс-заявки, и мы предпочли вернуть ошибку вместо блокировки запроса. – Ismael

+0

Хотелось бы, чтобы это было правдой. Это правда, если соединение потеряно в середине времени выполнения. Но если попытка подключения * first * не удалась (поскольку БД mongo не работает), драйвер никогда не повторяет попытку. – joeytwiddle

2

@ Клайв answer был превосходным.Тем не менее, в связи с использованием mongoose с Promise я получаю следующее предупреждение после каждой неудачной попытки:

(node:18123) 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 событий.

0

После прочтения документов, я уверен, что у вас есть неправильные варианты. Строка Варианты подключения должна выглядеть следующим образом:

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

+0

Варианты менялись с течением времени. Вопрос был создан 4 года назад. – kentor

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 после подключения, чтобы предотвратить отторжение необработанного обещания):

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)); 
Смежные вопросы