Se reconnecter de manière fiable à MongoDB
mise à jour: j'utilise la version 2.1 sur le conducteur, contre 3,2
j'ai une application de noeud qui utilise MongoDB. Le problème que j'ai est que si le serveur MongoDB tombe en panne pour une raison quelconque, l'application ne se reconnecte pas. Pour ce faire, j'ai basé mes tests sur le code en ce tutoriel officiel.
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)
});
L'idée est d'exécuter ce script, puis arrêter mongod, puis redémarrez-le. Donc, nous y voilà:
essai 1: arrêter mongod pendant 10 Secondes!--13-->
arrêter MongoDb pendant 10 Secondes fait le résultat désiré: il va arrêter d'exécuter les requêtes pendant ces 10 secondes, et puis va les exécuter toutes une fois que le serveur est de retour ip
TEST 2: l'arrêt de mongod pendant 30 secondes
après exactement 30 secondes, je commence à obtenir:
{ [MongoError: topology was destroyed] name: 'MongoError', message: 'topology was destroyed' }
insert
{ [MongoError: topology was destroyed] name: 'MongoError', message: 'topology was destroyed' }
<!-Le problème est qu'à partir de Maintenant, quand je redémarre mongod, la connexion n'est pas ré-implanter.
des Solutions?
est ce que ce problème a une solution? Si oui, savez-vous ce que c'est? Une fois que mon application commence à vomir "topologie a été détruit", le seul moyen d'obtenir tout fonctionne à nouveau est en redémarrant l'application entière...
5 réponses
il y a 2 options de connexion qui contrôlent la façon dont le pilote mongo nodejs se reconnecte après une panne de connexion
- reconnectTries: tenter de se reconnecter #fois (par défaut 30 fois)
- reconnectInterval: le serveur attendra # millisecondes entre les tentatives (par défaut 1000 ms)
référence sur mongo pilote docs
ce qui signifie que mongo va continuer à essayer de se connecter 30 fois par défaut et attendre 1 seconde avant chaque nouvelle tentative. C'est pourquoi vous commencez à voir des erreurs après 30 secondes.
vous devez modifier ces 2 paramètres en fonction de vos besoins comme cet échantillon.
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)
});
cela va essayer 60 fois au lieu de 30 par défaut, ce qui signifie que vous allez commencer à voir des erreurs après 60 secondes quand il arrête d'essayer de se reconnecter.
Note: si vous souhaitez empêcher l'application/demande d'attendre jusqu'à l'expiration de la période de reconnexion, vous devez passer l'option bufferMaxEntries: 0
. Le prix de c'est que les requêtes sont également interrompues lors de courtes interruptions du réseau.
par défaut, le pilote Mongo va essayer de se reconnecter 30 fois, une fois sur deux. Après cela, il n'essaiera plus de se reconnecter.
Vous pouvez régler le nombre de tentatives sur le nombre.MAX_VALUE pour garder la reconnexion "presque jamais":
var connection = "mongodb://127.0.0.1:27017/db";
MongoClient.connect(connection, {
server : {
reconnectTries : Number.MAX_VALUE,
autoReconnect : true
}
}, function (err, db) {
});
cela se produit parce que cela pourrait avoir dépassé la limite de connexion de Ré-essai. Après un certain nombre de tentatives, il détruit la connexion TCP et devient inactif. Donc, pour augmenter le nombre de tentatives et il serait mieux si vous augmentez le fossé entre les tentatives de connexion.
utilisez les options ci-dessous:
retryMiliSeconds {Number, default:5000}, number of milliseconds between retries.
numberOfRetries {Number, default:5}, number of retries off connection.
pour plus de détails, voir ce lien https://mongodb.github.io/node-mongodb-native/driver-articles/mongoclient.html
Solution:
MongoClient.connect("mongodb://localhost:27017/integration_test_?", {
db: {
native_parser: false,
retryMiliSeconds: 100000,
numberOfRetries: 100
},
server: {
socketOptions: {
connectTimeoutMS: 500
}
}
}, callback)
le comportement peut différer selon les différentes versions du pilote. Vous devriez mentionner votre version pilote.
version du pilote : 2.2.10 (dernière) mongo db version: 3.0.7
le code ci-dessous va prolonger le temps que mongod peut prendre pour revenir.
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);
le deuxième argument peut être utilisé pour passer les options du serveur.
paquet.json: "mongodb": "3.1.3"
Reconnecter les connexions existantes
pour affiner la configuration de reconnexion pour les connexions pré-établies, vous pouvez modifier le reconnectTries
/reconnectInterval
options (valeurs par défaut et autres documents ici).
reconnecter la connexion initiale
pour la connexion initiale, le client mongo ne se reconnecte pas s'il rencontre une erreur (voir ci-dessous). je crois qu'il devrait, mais dans entre-temps, j'ai créé la solution de contournement suivantepromise-retry
bibliothèque (qui utilise une stratégie de recul exponentiel).
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 }
Erreur De Connexion Initiale De Mongo:failed to connect to server [db:27017] on first connect