mongoError: la topologia è stata distrutta


163

Ho un servizio REST integrato in node.js con Restify e Mongoose e un mongoDB con una raccolta con circa 30.000 documenti di dimensioni regolari. Ho il mio servizio nodo in esecuzione attraverso pmx e pm2.

Ieri, improvvisamente, il nodo ha iniziato a cogliere errori con il messaggio "MongoError: la topologia è stata distrutta", niente di più. Non ho idea di cosa si intenda per questo e cosa potrebbe averlo innescato. non c'è molto da trovare anche quando si cerca su Google. Quindi ho pensato di chiedere qui.

Dopo aver riavviato il servizio nodo oggi, gli errori hanno smesso di entrare. Ne ho anche uno in esecuzione in produzione e mi spaventa che ciò possa accadere in qualsiasi momento in una parte piuttosto cruciale dell'installazione in esecuzione lì ...

Sto usando le seguenti versioni dei pacchetti citati:

  • mangusta: 4.0.3
  • restify: 3.0.3
  • nodo: 0.10.25

2
Ho problemi simili usando solo il driver
mongodb

1
Non sto usando le vele, quindi no, non penso che risolverebbe il mio problema
Dreagan

Risposte:


98

Sembra significare che la connessione del tuo server del nodo all'istanza MongoDB è stata interrotta mentre cercava di scrivere su di essa.

Dai un'occhiata al codice sorgente Mongo che genera quell'errore

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

Ciò non sembra essere correlato al problema di Sails citato nei commenti, in quanto non sono stati installati aggiornamenti per far precipitare il crash o la "correzione"


2
Ho lo stesso problema e succede quasi ogni settimana e chiude l'applicazione lavorando con mongo, è questo qualche problema che ho generato o questo è un problema in mongoose?
Mohammad Ganji,

@MohammadGanji: ottengo questo errore senza Mongoose, mentre eseguo il debug del codice client e non sono abbastanza veloce nel passare le istruzioni. Non sono sicuro di ciò che lo causa, ma l'impostazione dei punti di interruzione subito dopo le query mongo lo evita.
Dan Dascalescu,

@DanDascalescu Ho dimenticato di menzionare che il mio problema è stato risolto, era un problema con la registrazione, sembra che ci sia stato un avviso nei registri che dopo qualche tempo ha richiesto circa un gigabyte di spazio di archiviazione e ha chiuso il processo di mongo, quindi ho provato a zippare e fare il backup e problema risolto
Mohammad Ganji,

83

So che la risposta di Jason è stata accettata, ma ho avuto lo stesso problema con Mongoose e ho scoperto che il servizio che ospita il mio database ha raccomandato di applicare le seguenti impostazioni per mantenere viva la connessione di Mongodb nella produzione:

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

Spero che questa risposta possa aiutare altre persone ad avere errori "La topologia è stata distrutta".


4
Questo non ha risolto il problema per me. In realtà ho finito per aumentare il mio keepAlive a 30000, il che mi ha aiutato moltissimo. Anche se ho ancora l'errore di topologia occasionale ancora entrare.
ifightcrime

9
usando il driver Mongo dalla versione 3.4.2, queste opzioni devono essere al massimo livello: opzioni: {keepAlive: 1, connectTimeoutMS: 30000, reconnectTries: 30, reconnectInterval: 5000}
Sebastien H.

Ottengo questo errore senza Mongoose, mentre eseguo il debug del codice client e non sono abbastanza veloce nel passare le istruzioni. Non sono sicuro di ciò che lo causa, ma l'impostazione dei punti di interruzione subito dopo le query mongo lo evita.
Dan Dascalescu,

76

Questo errore è dovuto al fatto che il driver mongo ha interrotto la connessione per qualsiasi motivo (ad esempio il server era inattivo).

Di default mongoose proverà a riconnettersi per 30 secondi, quindi smetterà di riprovare e genererà errori per sempre fino al riavvio.

Puoi cambiarlo modificando questi 2 campi nelle opzioni di connessione

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

documentazione delle opzioni di connessione


3
Sì. Tecnicamente la risposta accettata risponde alla domanda posta MA questo è il modo giusto per evitare lo scenario in discussione.
Kingdango,

3
usando il driver Mongo dalla versione 3.4.2, queste opzioni devono essere al massimo livello: opzioni: {keepAlive: 1, connectTimeoutMS: 30000, reconnectTries: 30, reconnectInterval: 2000}
Sebastien H.

1
Per chiarire, secondo la documentazione del driver Nodo MongoDB , per impostazione predefinita il server tenterebbe di riconnettersi 30 volte, con un secondo di distanza tra ogni tentativo.
Boaz,

4
Non è necessario fornire queste opzioni sotto l'oggetto server ora. Va direttamente agli oggetti opzioni.
Animesh Singh,

3
Volevo solo aggiungere che le versioni recenti di mangusta hanno quelle opzioni ai massimi livelli, quindi non c'è bisogno di aggiungere server: {ecc.
Alex K

17

Nel mio caso, questo errore è stato causato da una db.close();sezione "wait" all'interno di "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
});

2
Nel caso di Carlos, immagino che la chiusura sia avvenuta prima di ogni altra cosa. Il mio caso era simile: ho effettuato l'accesso al DB dopo averlo chiuso. Sarebbe bello se gli sviluppatori Mongo potessero produrre messaggi di errore più espliciti. La "Topologia rotta" suona come una nota interna.
Juan Lanus,

3
la tua soluzione era quella di spostare il blocco db.closein un thenblocco, giusto?
AlexChaffee,

È corretto, nel mio caso elimino solo la riga db.close (), ma spostarla in un blocco quindi sembra essere una buona soluzione.
Carlos Rodríguez,

1
Lo spostamento db.closein un thenblocco ha funzionato perfettamente con il driver Node.js MongoDB nativo.
kevinmicke,

12

Solo una piccola aggiunta alla risposta di Gaafar, mi ha dato un avvertimento di deprecazione. Invece che sull'oggetto server, in questo modo:

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

Può andare sull'oggetto di livello superiore. Fondamentalmente, basta estrarlo dall'oggetto server e inserirlo nell'oggetto opzioni in questo modo:

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

7

"La topologia è stata distrutta" potrebbe essere causata dalla disconnessione di mangusta prima della creazione degli indici dei documenti di Mongo, secondo questo commento

Per assicurarsi che tutti i modelli abbiano i loro indici costruiti prima di disconnettersi, è possibile:

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

await mongoose.disconnect();

grazie, se stai eseguendo test case - questa è probabilmente una risposta molto probabile ...
Nick H247

1
Questo è stato per me. Grazie! Stavo eseguendo dei test a Jest con mongodb-memory-server, ottenendo sporadici errori sulla topologia o aprendo handle / promesse non finite. Ma a volte ha funzionato. Aggiunta di un'attesa sugli indici risolto.
roblingle

Ottengo questo errore senza Mongoose, mentre eseguo il debug del codice Jest come @roblingle e non sono abbastanza veloce nel scavalcare le dichiarazioni. Non sono sicuro di ciò che lo causa, ma l'impostazione dei punti di interruzione subito dopo le query mongo lo evita.
Dan Dascalescu,

@roblingle come hai finito per risolverlo? Ho appena riscontrato questo problema e mi ha reso impossibile riconnettermi a MongoDB. Da allora ho cancellato tutto e reinstallato MongoDB (tramite homebrew) e ora non funzionerà più all'avvio. (Potrebbe essere un problema indipendente)
Bobbyz,

Sembra non correlato. La mia app ha funzionato bene ma i test falliscono.
roblingle,

3

Il commento di Sebastian alla risposta di Adrien ha bisogno di più attenzione che mi ha aiutato, ma essendo un commento potrebbe essere ignorato qualche volta, quindi ecco una soluzione :

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

2

Ho anche avuto lo stesso errore. Alla fine, ho scoperto che ho qualche errore sul mio codice. Uso il bilanciamento del carico per due server nodejs, ma aggiorno semplicemente il codice di un server.

Cambio il mio server mongod from standalone to replication, ma dimentico di fare l'aggiornamento corrispondente per la stringa di connessione, quindi ho riscontrato questo errore.

stringa di connessione autonoma: mongodb://server-1:27017/mydb stringa di connessione di replica: mongodb://server-1:27017,server-2:27017,server-3:27017/mydb?replicaSet=myReplSet

dettagli qui :[mongo doc per stringa di connessione]


2

L'ho incontrato in kubernetes / minikube + nodejs + ambiente mongoose. Il problema era che il servizio DNS era in una sorta di latenza. Verificare che DNS sia pronto ha risolto il mio problema.

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

(i numeri in db_options sono trovati arbitrariamente su stackoverflow e siti simili simili)


2

Ecco cosa ho fatto, funziona benissimo. Il problema era scomparso dopo aver aggiunto le opzioni seguenti.

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

});

2

È necessario riavviare mongo per risolvere l'errore di topologia, quindi modificare alcune opzioni di mongoose o mongoclient per superare questo problema:

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

mongoose.connect(mongoDevString,mongoOptions);

Benvenuti in SO! Si prega di modificare la tua risposta e aggiungere qualche informazione in più, vale a dire come si risolve il problema, per più informazioni vedi stackoverflow.com/help/how-to-ask
B - Rian

1

Ho ricevuto questo errore, mentre stavo creando un nuovo database sulla mia community bussola MongoDb. Il problema era con il mio Mongod, non funzionava. Quindi, per risolvere il problema, ho dovuto eseguire il comando Mongod come precedente.

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

Sono stato in grado di creare un database dopo aver eseguito quel comando.

Spero che sia d'aiuto.


1

Ho avuto difficoltà con questo per un po 'di tempo - Come puoi vedere da altre risposte, il problema può essere molto diverso.

Il modo più semplice per scoprire che cosa sta causando è attivare loggerLevel: 'info'le opzioni


0

Nel mio caso, questo errore è stato causato da un'istanza del server identica già in esecuzione in background.

La cosa strana è che quando ho avviato il mio server senza preavviso ce n'è già uno in esecuzione, la console non ha mostrato nulla di simile a "qualcosa sta usando la porta xxx". Potrei anche caricare qualcosa sul server. Quindi, ho impiegato parecchio tempo per individuare questo problema.

Inoltre, dopo aver chiuso tutte le applicazioni che posso immaginare, non riuscivo ancora a trovare il processo che utilizza questa porta nel monitor delle attività del mio Mac. Devo usarelsof per rintracciare. Il colpevole non era sorprendente: è un processo di nodo. Tuttavia, con il PID mostrato nel terminale, ho scoperto che il numero di porta nel monitor è diverso da quello utilizzato dal mio server.

Tutto sommato, uccidere tutti i processi del nodo può risolvere direttamente questo problema.


-3

Ho risolto questo problema con:

  1. assicurando che mongo stia funzionando
  2. riavvio del mio server

4
Ciò non impedisce che il problema si ripeta
Sam Munroe,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.