ACTUALIZACIÓN: Estoy usando la versión 2.1 en el controlador, contra 3.2
Tengo una aplicación de nodo que utiliza MongoDB. El problema que tengo es que si el servidor MongoDB se desactiva por alguna razón, la aplicación no se vuelve a conectar. Para hacerlo bien, basé mis pruebas en el código de este tutorial oficial .
var MongoClient = require('mongodb').MongoClient , f = require('util').format; MongoClient.connect('mongodb://localhost:27017/test', // Optional: uncomment if necessary // { db: { bufferMaxEntries: 3 } }, function(err, db) { var col = db.collection('t'); setInterval(function() { col.insert({a:1}, function(err, r) { console.log("insert") console.log(err) col.findOne({}, function(err, doc) { console.log("findOne") console.log(err) }); }) }, 1000) });
La idea es ejecutar este script, y luego detener mongod, y luego reiniciarlo. Así que, aquí vamos:
Al detener MongoDb durante 10 segundos se obtiene el resultado deseado: dejará de ejecutar las consultas durante esos 10 segundos y luego se ejecutarán todas una vez que el servidor vuelva a ip
Después de exactamente 30 segundos, empiezo a recibir:
{ [MongoError: topology was destroyed] name: 'MongoError', message: 'topology was destroyed' } insert { [MongoError: topology was destroyed] name: 'MongoError', message: 'topology was destroyed' }
El problema es que a partir de esto, cuando reinicio mongod, la conexión no se vuelve a establecer .
¿Este problema tiene solución? Si es así, ¿sabes lo que es? Una vez que mi aplicación comienza a vomitar “la topología fue destruida”, la única manera de hacer que todo vuelva a funcionar es reiniciando toda la aplicación …
Hay 2 opciones de conexión que controlan cómo el controlador mongo nodejs se vuelve a conectar después de que la conexión falla
referencia en mongo drivers docs
Lo que significa que mongo seguirá intentando conectarse 30 veces de forma predeterminada y esperará 1 segundo antes de cada rebash. Es por eso que empiezas a ver errores después de 30 segundos.
Debe ajustar estos 2 parámetros según sus necesidades, como este ejemplo.
var MongoClient = require('mongodb').MongoClient, f = require('util').format; MongoClient.connect('mongodb://localhost:27017/test', { // retry to connect for 60 times reconnectTries: 60, // wait 1 second before retrying reconnectInterval: 1000 }, function(err, db) { var col = db.collection('t'); setInterval(function() { col.insert({ a: 1 }, function(err, r) { console.log("insert") console.log(err) col.findOne({}, function(err, doc) { console.log("findOne") console.log(err) }); }) }, 1000) });
Esto intentará 60 veces en lugar de los 30 predeterminados, lo que significa que comenzará a ver errores después de 60 segundos cuando deje de intentar volver a conectarse.
Nota: si desea evitar que la aplicación / solicitud espere hasta el vencimiento del período de reconexión, debe pasar la opción bufferMaxEntries: 0
. El precio para esto es que las solicitudes también se abortan durante interrupciones cortas de la red.
Por defecto, el controlador Mongo intentará volver a conectarse 30 veces, una por segundo. Después de eso no volverá a intentar volver a conectarse.
Puede establecer el número de rebashs en Number.MAX_VALUE para mantenerlo reconectando “casi para siempre”:
var connection = "mongodb://127.0.0.1:27017/db"; MongoClient.connect(connection, { server : { reconnectTries : Number.MAX_VALUE, autoReconnect : true } }, function (err, db) { });
Está sucediendo porque podría haber cruzado el límite de conexión de rebash. Después del número de rebashs, destruye la conexión TCP y queda inactivo. Por lo tanto, aumente el número de rebashs y sería mejor si boosta la brecha entre los rebashs de conexión.
Utilice las siguientes opciones:
retryMiliSeconds {Number, default:5000}, number of milliseconds between retries. numberOfRetries {Number, default:5}, number of retries off connection.
Para obtener más información, consulte este enlace https://mongodb.github.io/node-mongodb-native/driver-articles/mongoclient.html
Solución:
MongoClient.connect("mongodb://localhost:27017/integration_test_?", { db: { native_parser: false, retryMiliSeconds: 100000, numberOfRetries: 100 }, server: { socketOptions: { connectTimeoutMS: 500 } } }, callback)
El comportamiento puede diferir con las diferentes versiones del controlador. Debe mencionar su versión de controlador.
versión del controlador: 2.2.10 (más reciente) versión de db mongo: 3.0.7
El código siguiente extenderá el tiempo que mongod puede tardar en volver a subir.
var MongoClient = require('mongodb').MongoClient , f = require('util').format; function connectCallback(err, db) { var col = db.collection('t'); setInterval(function() { col.insert({a:1}, function(err, r) { console.log("insert") console.log(err) col.findOne({}, function(err, doc) { console.log("findOne") console.log(err) }); }) }, 1000) } var options = { server: { reconnectTries: 2000,reconnectInterval: 1000 }} MongoClient.connect('mongodb://localhost:27017/test',options,connectCallback);
El segundo argumento puede usarse para pasar las opciones del servidor.
"mongodb": "3.1.3"
Para ajustar la configuración de reconexión para las conexiones preestablecidas, puede modificar las opciones de reconnectTries
/ reconnectInterval
( valores predeterminados y documentación adicional aquí ).
Para la conexión inicial, el cliente mongo no se vuelve a conectar si encuentra un error (ver más abajo). Creo que debería , pero mientras tanto, he creado la siguiente solución utilizando la biblioteca promise-retry
(que utiliza una estrategia de retroceso exponencial).
const promiseRetry = require('promise-retry') const MongoClient = require('mongodb').MongoClient const options = { useNewUrlParser: true, reconnectTries: 60, reconnectInterval: 1000, poolSize: 10, bufferMaxEntries: 0 } const promiseRetryOptions = { retries: options.reconnectTries, factor: 1.5, minTimeout: options.reconnectInterval, maxTimeout: 5000 } const connect = (url) => { return promiseRetry((retry, number) => { console.log(`MongoClient connecting to ${url} - retry number: ${number}`) return MongoClient.connect(url, options).catch(retry) }, promiseRetryOptions) } module.exports = { connect }
Error de conexión inicial de Mongo: failed to connect to server [db:27017] on first connect