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...

21
demandé sur Merc 2016-09-29 19:46:44

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.

19
répondu Gaafar 2017-09-01 12:04:56

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) {

    });
4
répondu Javier Ferrero 2016-10-03 13:24:25

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)
2
répondu Developer 2017-10-09 16:46:26

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.

1
répondu inaitgaJ 2016-10-03 14:39:23

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

0
répondu Nick Grealy 2018-08-24 06:16:53