mongoError: la topologie a été détruite

163

J'ai un service REST intégré à node.js avec Restify et Mongoose et un mongoDB avec une collection d'environ 30.000 documents de taille régulière. Mon service de nœud fonctionne via pmx et pm2.

Hier, soudainement, le nœud a commencé à chercher des erreurs avec le message "MongoError: Topology was destroy", rien de plus. Je n'ai aucune idée de ce que cela signifie et de ce qui aurait pu déclencher cela. il n'y a pas grand-chose à trouver lors de la recherche sur Google. Alors j'ai pensé que je demanderais ici.

Après avoir redémarré le service de nœud aujourd'hui, les erreurs ont cessé d'arriver. J'en ai également une en cours de production et cela me fait peur que cela puisse arriver à tout moment à une partie assez cruciale de la configuration qui y est exécutée ...

J'utilise les versions suivantes des packages mentionnés:

  • mangouste: 4.0.3
  • restifier: 3.0.3
  • nœud: 0.10.25
dreagan
la source
2
J'ai des problèmes similaires en utilisant uniquement le pilote
mongodb
1
Je n'utilise pas de voiles, donc non, je ne pense pas que cela
résoudrait

Réponses:

98

Cela semble signifier que la connexion de votre serveur de nœuds à votre instance MongoDB a été interrompue pendant qu'il essayait d'écrire dessus.

Jetez un œil au code source Mongo qui génère cette erreur

Mongos.prototype.insert = function(ns, ops, options, callback) {
    if(typeof options == 'function') callback = options, options = {};
    if(this.s.state == DESTROYED) return callback(new MongoError(f('topology was destroyed')));
    // Topology is not connected, save the call in the provided store to be
    // Executed at some point when the handler deems it's reconnected
    if(!this.isConnected() && this.s.disconnectHandler != null) {
      callback = bindToCurrentDomain(callback);
      return this.s.disconnectHandler.add('insert', ns, ops, options, callback);
    }

    executeWriteOperation(this.s, 'insert', ns, ops, options, callback);
}

Cela ne semble pas être lié au problème de Sails cité dans les commentaires, car aucune mise à niveau n'a été installée pour précipiter le crash ou le «correctif»

Jason Nichols
la source
2
J'ai le même problème et cela arrive presque toutes les semaines et arrête l'application fonctionnant avec mongo, est-ce un problème que j'ai généré ou est-ce un problème chez mangouste?
Mohammad Ganji
@MohammadGanji: J'obtiens cette erreur sans Mongoose, en déboguant le code client et en n'étant pas assez rapide pour parcourir les instructions. Je ne suis pas sûr de la cause, mais la définition de points d'arrêt juste après les requêtes mongo l'évite.
Dan Dascalescu
@DanDascalescu J'ai oublié de mentionner que mon problème a été résolu, c'était un problème de journalisation, on dirait qu'il y avait un avertissement dans les journaux qui, après un certain temps, a pris environ un gigaoctet de stockage et arrêté le processus mongo, alors j'ai essayé de zipper et de sauvegarder et problème résolu
Mohammad Ganji
83

Je sais que la réponse de Jason a été acceptée, mais j'ai eu le même problème avec Mongoose et j'ai constaté que le service hébergeant ma base de données recommandait d'appliquer les paramètres suivants afin de maintenir la connexion de Mongodb en production:

var options = {
  server: { socketOptions: { keepAlive: 1, connectTimeoutMS: 30000 } },
  replset: { socketOptions: { keepAlive: 1, connectTimeoutMS: 30000 } }
};
mongoose.connect(secrets.db, options);

J'espère que cette réponse pourra aider d'autres personnes ayant des erreurs "La topologie a été détruite".

Adrien Joly
la source
4
Cela n'a pas résolu le problème pour moi. En fait, j'ai fini par augmenter mon keepAlive à 30000, ce qui a énormément aidé. Même si j'obtiens toujours une erreur de topologie occasionnelle.
ifightcrime
9
en utilisant le pilote Mongo de la version 3.4.2, ces options doivent être au plus haut niveau: options: {keepAlive: 1, connectTimeoutMS: 30000, reconnectTries: 30, reconnectInterval: 5000}
Sebastien H.
J'obtiens cette erreur sans Mongoose, lors du débogage du code client et de ne pas être assez rapide pour parcourir les instructions. Je ne sais pas ce qui le cause, mais la définition de points d'arrêt juste après les requêtes mongo l'évite.
Dan Dascalescu
76

Cette erreur est due au fait que le pilote mongo a interrompu la connexion pour une raison quelconque (le serveur était en panne par exemple).

Par défaut, la mangouste essaiera de se reconnecter pendant 30 secondes, puis arrêtera de réessayer et lancera des erreurs pour toujours jusqu'au redémarrage.

Vous pouvez changer cela en éditant ces 2 champs dans les options de connexion

mongoose.connect(uri, 
    { server: { 
        // sets how many times to try reconnecting
        reconnectTries: Number.MAX_VALUE,
        // sets the delay between every retry (milliseconds)
        reconnectInterval: 1000 
        } 
    }
);

documentation des options de connexion

gafi
la source
3
Oui. Techniquement, la réponse acceptée répond à la question posée MAIS c'est la bonne façon d'éviter le scénario en discussion.
kingdango
3
en utilisant le pilote Mongo de la version 3.4.2, ces options doivent être au niveau supérieur: options: {keepAlive: 1, connectTimeoutMS: 30000, reconnectTries: 30, reconnectInterval: 2000}
Sebastien H.
1
Pour clarifier, selon la documentation du pilote Node MongoDB , par défaut, le serveur tenterait de se reconnecter 30 fois, avec une seconde d'intervalle entre chaque nouvelle tentative.
Boaz
4
Vous n'avez pas besoin de fournir ces options sous l'objet serveur maintenant. Il va directement aux objets d'options.
Animesh Singh
3
Je voulais juste ajouter que les versions récentes de mangouste ont ces options de niveau supérieur, donc pas besoin d'ajouter server: {etc.
Alex K
17

Dans mon cas, cette erreur a été causée par une section db.close();hors d'une section 'await' à l'intérieur de 'async'

MongoClient.connect(url, {poolSize: 10, reconnectTries: Number.MAX_VALUE, reconnectInterval: 1000}, function(err, db) {
    // Validate the connection to Mongo
    assert.equal(null, err);    
    // Query the SQL table 
    querySQL()
    .then(function (result) {
        console.log('Print results SQL');
        console.log(result);
        if(result.length > 0){

            processArray(db, result)
            .then(function (result) {
                console.log('Res');
                console.log(result);
            })
            .catch(function (err) {
                console.log('Err');
                console.log(err);
            })
        } else {
            console.log('Nothing to show in MySQL');
        }
    })
    .catch(function (err) {
        console.log(err);
    });
    db.close(); // <--------------------------------THIS LINE
});
Carlos Rodríguez
la source
2
Dans le cas de Carlos, je suppose que la clôture s'est produite avant tout le reste. Mon cas était similaire: j'ai accédé à la base de données après l'avoir fermée. Ce serait bien si les développeurs Mongo pouvaient produire des messages d'erreur plus explicites. La "Topologie cassée" sonne comme une note interne.
Juan Lanus le
3
votre solution était de déplacer le db.closedans un thenbloc, non?
AlexChaffee
C'est correct, dans mon cas je supprime uniquement la ligne db.close (), mais la déplacer dans un bloc then semble être une bonne solution.
Carlos Rodríguez
1
Déplacer le db.closevers un thenbloc a très bien fonctionné pour moi avec le pilote natif MongoDB Node.js.
kevinmicke
12

Juste un ajout mineur à la réponse de Gaafar, cela m'a donné un avertissement de dépréciation. Au lieu de sur l'objet serveur, comme ceci:

MongoClient.connect(MONGO_URL, {
    server: {
        reconnectTries: Number.MAX_VALUE,
        reconnectInterval: 1000
    }
});

Il peut aller sur l'objet de niveau supérieur. En gros, retirez-le simplement de l'objet serveur et placez-le dans l'objet options comme ceci:

MongoClient.connect(MONGO_URL, {
    reconnectTries: Number.MAX_VALUE,
    reconnectInterval: 1000
});
codinaire
la source
7

"La topologie a été détruite" peut être causée par la déconnexion de la mangouste avant la création des index de documents mongo, selon ce commentaire

Afin de vous assurer que tous les modèles ont leurs index créés avant de se déconnecter, vous pouvez:

await Promise.all(mongoose.modelNames().map(model => mongoose.model(model).ensureIndexes()));

await mongoose.disconnect();
golfadas
la source
merci, si vous exécutez des cas de test - c'est probablement une réponse très probable ...
Nick H247
1
C'était tout pour moi. Je vous remercie! J'exécutais des tests dans Jest avec mongodb-memory-server, obtenant des erreurs sporadiques sur la topologie ou des poignées ouvertes / des promesses inachevées. Mais parfois cela fonctionnait. L'ajout d'une attente sur les index l'a corrigé.
roblingle le
J'obtiens cette erreur sans Mongoose, en déboguant du code Jest comme @roblingle et en ne pas être assez rapide pour franchir les instructions. Je ne sais pas ce qui le cause, mais la définition de points d'arrêt juste après les requêtes mongo l'évite.
Dan Dascalescu
@roblingle comment avez-vous fini par le réparer? Je viens de rencontrer ce problème et il m'est impossible de me connecter à nouveau à MongoDB. Depuis, j'ai tout supprimé et réinstallé MongoDB (via homebrew) et maintenant il ne fonctionnera plus au démarrage. (Peut-être un problème sans rapport)
bobbyz
Cela semble sans rapport. Mon application a bien fonctionné mais les tests échouent.
roblingle
3

Le commentaire de Sebastian sur la réponse d'Adrien a besoin de plus d'attention, cela m'a aidé, mais il peut être ignoré parfois, alors voici une solution :

var options =  { useMongoClient: true, keepAlive: 1, connectTimeoutMS: 30000, reconnectTries: 30, reconnectInterval: 5000 }
mongoose.connect(config.mongoConnectionString, options, (err) => {
    if(err) {
        console.error("Error while connecting", err);
    }
});
Black Mamba
la source
2

J'ai également eu la même erreur. Enfin, j'ai trouvé que j'avais une erreur sur mon code. J'utilise l'équilibrage de charge pour deux serveurs nodejs, mais je mets simplement à jour le code d'un serveur.

Je change de serveur mongod from standalone to replication , mais j'oublie de faire la mise à jour correspondante pour la chaîne de connexion, j'ai donc rencontré cette erreur.

chaîne de connexion autonome: mongodb://server-1:27017/mydb chaîne de connexion de réplication: mongodb://server-1:27017,server-2:27017,server-3:27017/mydb?replicaSet=myReplSet

détails ici :[mongo doc for connection string]

lutaoact
la source
2

J'ai rencontré cela dans l'environnement kubernetes / minikube + nodejs + mongoose. Le problème était que le service DNS était en place avec une sorte de latence. Vérifier que DNS est prêt a résolu mon problème.

const dns = require('dns');

var dnsTimer = setInterval(() => {
	dns.lookup('mongo-0.mongo', (err, address, family) => {
		if (err) {
			console.log('DNS LOOKUP ERR', err.code ? err.code : err);
		} else {
			console.log('DNS LOOKUP: %j family: IPv%s', address, family);
			clearTimeout(dnsTimer);
			mongoose.connect(mongoURL, db_options);
		}
	});
}, 3000);


var db = mongoose.connection;
var db_options = {
	autoReconnect:true,

	poolSize: 20,
	socketTimeoutMS: 480000,
	keepAlive: 300000,

	keepAliveInitialDelay : 300000,
	connectTimeoutMS: 30000,
	reconnectTries: Number.MAX_VALUE,
	reconnectInterval: 1000,
	useNewUrlParser: true
};

(les nombres dans db_options sont arbitraires trouvés sur stackoverflow et des sites similaires)

tkrizsa
la source
2

Voici ce que j'ai fait, cela fonctionne très bien. Le problème a disparu après l'ajout des options ci-dessous.

const dbUrl = "mongodb://localhost:27017/sampledb";
const options =  { useMongoClient: true, keepAlive: 1, connectTimeoutMS: 30000, reconnectTries: 30, reconnectInterval: 5000, useNewUrlParser: true }
mongoose.connect(dbUrl,options, function(
  error
) {
  if (error) {
    console.log("mongoerror", error);
  } else {
    console.log("connected");
  }

});
Thavaprakash Swaminathan
la source
2

Vous devez redémarrer mongo pour résoudre l'erreur de topologie, puis modifiez simplement certaines options de mongoose ou mongoclient pour surmonter ce problème:

var mongoOptions = {
    useMongoClient: true,
    keepAlive: 1,
    connectTimeoutMS: 30000,
    reconnectTries: Number.MAX_VALUE,
    reconnectInterval: 5000,
    useNewUrlParser: true
}

mongoose.connect(mongoDevString,mongoOptions);
Ganesh sharma
la source
Bienvenue à SO! Veuillez modifier votre réponse et ajouter des informations supplémentaires, c'est-à-dire comment cela résout le problème, pour plus de conseils, consultez stackoverflow.com/help/how-to-ask
B - rian
1

J'ai eu cette erreur alors que je créais une nouvelle base de données sur ma communauté MongoDb Compass. Le problème était avec mon Mongod, il ne fonctionnait pas. Donc, comme solution, j'ai dû exécuter la commande Mongod comme précédemment.

C:\Program Files\MongoDB\Server\3.6\bin>mongod

J'ai pu créer une base de données après avoir exécuté cette commande.

J'espère que ça aide.

Sibeesh Venu
la source
1

Je me débattais avec cela pendant un certain temps - Comme vous pouvez le voir dans d'autres réponses, le problème peut être très différent.

Le moyen le plus simple de découvrir ce qui cause est de l'activer loggerLevel: 'info'dans les options

orepor
la source
0

Dans mon cas, cette erreur a été causée par une instance de serveur identique exécutant déjà en arrière-plan.

Ce qui est étrange, c'est que lorsque j'ai démarré mon serveur sans préavis, il y en a déjà un en cours d'exécution, la console n'affiche rien du genre «quelque chose utilise le port xxx». Je pourrais même télécharger quelque chose sur le serveur. Donc, il m'a fallu assez de temps pour localiser ce problème.

De plus, après avoir fermé toutes les applications que j'imagine, je n'ai toujours pas trouvé le processus qui utilise ce port dans le moniteur d'activité de mon Mac. Je dois utiliserlsof pour tracer. Le coupable n'était pas surprenant - c'est un processus de nœud. Cependant, avec le PID affiché dans le terminal, j'ai trouvé que le numéro de port du moniteur était différent de celui utilisé par mon serveur.

Dans l'ensemble, tuer tous les processus de nœud peut résoudre ce problème directement.

AnLuoRidge
la source
-3

J'ai résolu ce problème en:

  1. s'assurer que mongo fonctionne
  2. redémarrer mon serveur
maia
la source
4
Cela n'empêche pas le problème de se reproduire
Sam Munroe