mongoError: Die Topologie wurde zerstört

163

Ich habe einen REST-Service in node.js mit Restify und Mongoose und eine mongoDB mit einer Sammlung mit etwa 30.000 Dokumenten normaler Größe. Ich habe meinen Knotendienst über pmx und pm2 ausgeführt.

Gestern fing der Knoten plötzlich an, Fehler mit der Meldung "MongoError: Topologie wurde zerstört" auszublenden, mehr nicht. Ich habe keine Ahnung, was damit gemeint ist und was dies möglicherweise ausgelöst haben könnte. Es gibt auch nicht viel zu finden, wenn Google dies sucht. Also dachte ich, ich würde hier fragen.

Nach dem heutigen Neustart des Knotendienstes sind die Fehler nicht mehr aufgetreten. Ich habe auch einen dieser Fehler in der Produktion und es macht mir Angst, dass dies zu einem bestimmten Zeitpunkt bei einem ziemlich wichtigen Teil des dort ausgeführten Setups passieren kann ...

Ich verwende die folgenden Versionen der genannten Pakete:

  • Mungo: 4.0.3
  • restify: 3.0.3
  • Knoten: 0,10,25
Träumer
quelle
2
Ich habe ähnliche Probleme mit nur dem Mongodb-Treiber :(
0x8890
1
Ich benutze keine Segel, also nein, ich glaube nicht, dass das mein Problem beheben würde
Dreagan

Antworten:

98

Dies scheint zu bedeuten, dass die Verbindung Ihres Knotenservers zu Ihrer MongoDB-Instanz unterbrochen wurde, während versucht wurde, darauf zu schreiben.

Schauen Sie sich den Mongo-Quellcode an, der diesen Fehler generiert

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);
}

Dies scheint nicht mit dem in den Kommentaren genannten Sails-Problem zu tun zu haben, da keine Upgrades installiert wurden, um den Absturz oder das "Update" auszulösen.

Jason Nichols
quelle
2
Ich habe das gleiche Problem und es passiert fast jede Woche und fährt die Anwendung mit Mongo herunter. Ist dies ein Problem, das ich generiert habe, oder ist dies ein Problem bei Mungo?
Mohammad Ganji
@MohammadGanji: Ich erhalte diesen Fehler ohne Mongoose, während ich Client-Code debugge und nicht schnell genug bin, um Anweisungen zu überschreiten. Ich bin nicht sicher, was es verursacht, aber das Setzen von Haltepunkten direkt nach den Mongo-Abfragen vermeidet es.
Dan Dascalescu
@DanDascalescu Ich habe vergessen zu erwähnen, dass mein Problem behoben wurde. Es war ein Problem mit der Protokollierung. Es sieht so aus, als ob in den Protokollen eine Warnung enthalten war, die nach einiger Zeit etwa ein Gigabyte Speicherplatz in Anspruch nahm und den Mongo-Prozess herunterfuhr. Deshalb habe ich versucht, die Daten zu komprimieren und zu sichern und Problem gelöst
Mohammad Ganji
83

Ich weiß, dass Jasons Antwort akzeptiert wurde, aber ich hatte das gleiche Problem mit Mongoose und stellte fest, dass der Dienst, der meine Datenbank hostet , die folgenden Einstellungen empfiehlt, um die Verbindung von Mongodb in der Produktion aufrechtzuerhalten:

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

Ich hoffe, dass diese Antwort anderen Personen mit Fehlern "Topologie wurde zerstört" hilft.

Adrien Joly
quelle
4
Dies hat das Problem für mich nicht behoben. Am Ende habe ich mein keepAlive auf 30000 erhöht, was enorm geholfen hat. Auch wenn ich immer noch gelegentlich Topologiefehler bekomme, kommt es immer noch.
ifightcrime
9
Bei Verwendung des Mongo-Treibers ab Version 3.4.2 müssen sich diese Optionen auf der obersten Ebene befinden: Optionen: {keepAlive: 1, connectTimeoutMS: 30000, reconnectTries: 30, reconnectInterval: 5000}
Sebastien H.
Ich erhalte diesen Fehler ohne Mongoose, während ich Client-Code debugge und nicht schnell genug bin, um Anweisungen zu überschreiten. Ich bin mir nicht sicher, was es verursacht, aber das Setzen von Haltepunkten direkt nach den Mongo-Abfragen vermeidet es.
Dan Dascalescu
76

Dieser Fehler ist darauf zurückzuführen, dass der Mongo-Treiber die Verbindung aus irgendeinem Grund unterbrochen hat (Server war beispielsweise ausgefallen).

Standardmäßig versucht Mungo 30 Sekunden lang, die Verbindung wiederherzustellen, hört dann auf, es erneut zu versuchen, und wirft Fehler für immer aus, bis sie neu gestartet werden.

Sie können dies ändern, indem Sie diese beiden Felder in den Verbindungsoptionen bearbeiten

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

Dokumentation der Verbindungsoptionen

Gafi
quelle
3
Ja. Technisch beantwortet die akzeptierte Antwort die gestellte Frage, ABER dies ist der richtige Weg, um das diskutierte Szenario zu vermeiden.
Kingdango
3
Bei Verwendung des Mongo-Treibers ab Version 3.4.2 müssen sich diese Optionen auf der obersten Ebene befinden: Optionen: {keepAlive: 1, connectTimeoutMS: 30000, reconnectTries: 30, reconnectInterval: 2000}
Sebastien H.
1
Zur Verdeutlichung würde der Server gemäß der Dokumentation des Node MongoDB-Treibers standardmäßig versuchen, die Verbindung 30 Mal wiederherzustellen, wobei zwischen jedem erneuten Versuch ein Abstand von einer Sekunde liegt.
Boaz
4
Sie müssen diese Optionen jetzt nicht unter dem Serverobjekt angeben. Es geht direkt zu den Optionsobjekten.
Animesh Singh
3
Ich wollte nur hinzufügen, dass neuere Versionen von Mungo diese Optionen in der obersten Ebene haben, also keine Notwendigkeit, server: {usw. hinzuzufügen .
Alex K
17

In meinem Fall wurde dieser Fehler durch einen db.close();Abschnitt "Warten" innerhalb von "Async" verursacht.

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
quelle
2
In Carlos 'Fall ist der Abschluss wohl vor allem anderen passiert. Mein Fall war ähnlich: Ich habe auf die Datenbank zugegriffen, nachdem ich sie geschlossen hatte. Es wäre schön, wenn die Mongo-Entwickler explizitere Fehlermeldungen erzeugen könnten. Die "Topologie defekt" klingt wie eine interne Notiz.
Juan Lanus
3
Ihre Lösung bestand darin, das db.closein einen thenBlock zu verschieben, richtig?
AlexChaffee
Es ist richtig, in meinem Fall lösche ich nur die Zeile db.close (), aber das Verschieben in einen then-Block scheint eine gute Lösung zu sein.
Carlos Rodríguez
1
Das Verschieben db.closein einen thenBlock hat für mich mit dem nativen MongoDB Node.js-Treiber hervorragend funktioniert.
Kevinmicke
12

Nur eine kleine Ergänzung zu Gaafars Antwort, gab es mir eine Abwertungswarnung. Anstelle des Serverobjekts wie folgt:

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

Es kann auf das Objekt der obersten Ebene gehen. Nehmen Sie es einfach aus dem Serverobjekt und fügen Sie es wie folgt in das Optionsobjekt ein:

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

"Topologie wurde zerstört" kann durch das Trennen der Mungo verursacht werden, bevor Mongo-Dokumentindizes gemäß diesem Kommentar erstellt werden

Um sicherzustellen, dass alle Modelle ihre Indizes erstellt haben, bevor Sie die Verbindung trennen, können Sie:

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

await mongoose.disconnect();
Golfadas
quelle
Vielen Dank, wenn Sie Testfälle
ausführen
1
Das war es für mich. Danke dir! Ich habe in Jest Tests mit Mongodb-Memory-Server durchgeführt und dabei sporadische Fehler in der Topologie oder offene Handles / unvollendete Versprechen erhalten. Aber manchmal hat es funktioniert. Durch Hinzufügen einer Wartezeit für Indizes wurde das Problem behoben.
Roblingle
Ich erhalte diesen Fehler ohne Mongoose, während ich Jest-Code wie @roblingle debugge und nicht schnell genug bin, um Anweisungen zu überschreiten. Ich bin mir nicht sicher, was es verursacht, aber das Setzen von Haltepunkten direkt nach den Mongo-Abfragen vermeidet es.
Dan Dascalescu
@roblingle wie bist du dazu gekommen, es zu reparieren? Ich bin gerade auf dieses Problem gestoßen und es war mir unmöglich, wieder eine Verbindung zu MongoDB herzustellen. Ich habe seitdem alles gelöscht und MongoDB (über Homebrew) neu installiert und jetzt läuft es beim Start nicht mehr. (
Kann
Klingt nicht verwandt. Meine App hat gut funktioniert, aber die Tests schlagen fehl.
Roblingle
3

Sebastians Kommentar zu Adriens Antwort braucht mehr Aufmerksamkeit, es hat mir geholfen, aber ein Kommentar könnte irgendwann ignoriert werden. Hier ist eine Lösung :

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);
    }
});
Schwarze Mamba
quelle
2

Ich hatte auch den gleichen Fehler. Schließlich stellte ich fest, dass mein Code einen Fehler enthält. Ich verwende den Lastausgleich für zwei NodeJS-Server, aktualisiere aber nur den Code eines Servers.

Ich ändere meinen Mongod-Server from standalone to replication, vergesse jedoch, das entsprechende Update für die Verbindungszeichenfolge durchzuführen , sodass dieser Fehler aufgetreten ist .

Standalone-Verbindungszeichenfolge: mongodb://server-1:27017/mydb Replikationsverbindungszeichenfolge: mongodb://server-1:27017,server-2:27017,server-3:27017/mydb?replicaSet=myReplSet

Details hier: [Mongo Doc für Verbindungszeichenfolge]

Lutaoact
quelle
2

Ich habe dies in der Umgebung von Kubernetes / Minikube + NodeJS + Mungo getroffen. Das Problem war, dass der DNS-Dienst eine Art Latenz hatte. Das Überprüfen von DNS ist bereit, mein Problem zu lösen.

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
};

(Die Zahlen in db_options sind willkürlich auf Stackoverflow und ähnlichen Sites zu finden.)

tkrizsa
quelle
2

Hier, was ich getan habe, funktioniert es gut. Das Problem wurde behoben, nachdem die folgenden Optionen hinzugefügt wurden.

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
quelle
2

Sie müssen mongo neu starten, um den Topologiefehler zu beheben, und dann nur einige Optionen von mongoose oder mongoclient ändern, um dieses Problem zu beheben:

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

mongoose.connect(mongoDevString,mongoOptions);
Ganesh Sharma
quelle
Willkommen bei SO! Bitte bearbeiten Sie Ihre Antwort und fügen Sie weitere Informationen hinzu, z. B. wie das Problem gelöst wird. Weitere Anleitungen finden Sie unter stackoverflow.com/help/how-to-ask
B - rian
1

Ich habe diesen Fehler erhalten, als ich eine neue Datenbank in meiner MongoDb Compass Community erstellt habe. Das Problem war mit meinem Mongod, es lief nicht. Als Fix musste ich den Mongod-Befehl wie oben ausführen.

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

Nach dem Ausführen dieses Befehls konnte ich eine Datenbank erstellen.

Ich hoffe es hilft.

Sibeesh Venu
quelle
1

Ich hatte einige Zeit damit zu kämpfen - Wie Sie anderen Antworten entnehmen können, kann das Problem sehr unterschiedlich sein.

Der einfachste Weg, um herauszufinden, was die Ursache ist, besteht darin, loggerLevel: 'info'die Optionen zu aktivieren

orepor
quelle
0

In meinem Fall wurde dieser Fehler durch eine identische Serverinstanz verursacht, auf der bereits Hintergrund ausgeführt wird.

Das Seltsame ist, als ich meinen Server ohne Vorankündigung startete, dass bereits einer läuft. Auf der Konsole wurde nichts angezeigt wie "Etwas verwendet Port xxx". Ich könnte sogar etwas auf den Server hochladen. Ich habe also ziemlich lange gebraucht, um dieses Problem zu lokalisieren.

Nachdem ich alle Anwendungen geschlossen hatte, die ich mir vorstellen kann, konnte ich den Prozess, der diesen Port verwendet, im Aktivitätsmonitor meines Mac immer noch nicht finden. Ich muss verwenden, um lsofzu verfolgen. Der Täter war nicht überraschend - es ist ein Knotenprozess. Mit der im Terminal angezeigten PID stellte ich jedoch fest, dass sich die Portnummer im Monitor von der von meinem Server verwendeten unterscheidet.

Alles in allem kann das Beenden aller Knotenprozesse dieses Problem direkt lösen.

AnLuoRidge
quelle
-3

Ich habe dieses Problem gelöst durch:

  1. Sicherstellen, dass Mongo läuft
  2. Neustart meines Servers
maia
quelle
4
Dies verhindert nicht, dass das Problem erneut
auftritt