mongoError: a topologia foi destruída

163

Eu tenho um serviço REST embutido no node.js com Restify e Mongoose e um mongoDB com uma coleção com cerca de 30.000 documentos de tamanho regular. Eu tenho o meu serviço de nó executando pmx e pm2.

Ontem, de repente, o nó começou a eliminar erros com a mensagem "MongoError: Topologia foi destruída", nada mais. Não tenho idéia do que se entende por isso e o que poderia ter provocado isso. também não há muito a ser encontrado ao pesquisar no google. Então pensei em perguntar aqui.

Depois de reiniciar o serviço do nó hoje, os erros pararam de aparecer. Eu também tenho um desses em execução na produção e me assusta que isso possa acontecer a qualquer momento para uma parte crucial da instalação em execução ...

Estou usando as seguintes versões dos pacotes mencionados:

  • mangusto: 4.0.3
  • restify: 3.0.3
  • nó: 0.10.25
dreagan
fonte
2
Estou tendo problemas semelhantes usando apenas o driver mongodb :(
0x8890 15/07/2015
1
Não estou usando velas, de modo nenhum, eu não acho que iria resolver o meu problema
dreagan

Respostas:

98

Parece significar que a conexão do servidor do nó com a instância do MongoDB foi interrompida enquanto ele tentava gravar.

Veja o código fonte do Mongo que gera esse erro

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

Isso não parece estar relacionado ao problema do Sails citado nos comentários, pois não foram instaladas atualizações para precipitar a falha ou a "correção"

Jason Nichols
fonte
2
Eu tenho o mesmo problema e isso acontece quase toda semana e desliga o aplicativo que funciona com o mongo. Isso é algum problema que eu gerei ou isso é um problema no mongoose?
Mohammad Ganji 24/04
@MohammadGanji: Eu recebo esse erro sem o Mongoose, enquanto depuro o código do cliente e não sou rápido o suficiente para passar por cima das instruções. Não sei o que causa isso, mas definir pontos de interrupção logo após as consultas do mongo evita isso.
Dan Dascalescu 26/09
@DanDascalescu Eu esqueci de mencionar que meu problema foi resolvido, era um problema com o log, parece que havia algum aviso nos logs que, depois de algum tempo, levou um gigabyte de armazenamento e desligou o processo do mongo, então tentei fechar e fazer backup e problema resolvido
Mohammad Ganji
83

Sei que a resposta de Jason foi aceita, mas tive o mesmo problema com o Mongoose e descobri que o serviço que hospedava meu banco de dados recomendava aplicar as seguintes configurações para manter a conexão do Mongodb ativa na produção:

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

Espero que esta resposta possa ajudar outras pessoas com erros "A topologia foi destruída".

Adrien Joly
fonte
4
Isso não resolveu o problema para mim. Na verdade, acabei aumentando meu keepAlive para 30000, o que ajudou tremendamente. Mesmo que eu ainda receba um erro ocasional de topologia, ainda assim.
Ifightcrime
9
usando Mongo motorista a partir da versão 3.4.2, estas opções precisam estar no nível superior: opções: {keepAlive: 1, connectTimeoutMS: 30000, reconnectTries: 30, reconnectInterval: 5000}
Sebastien H.
Eu recebo esse erro sem o Mongoose, durante a depuração do código do cliente e não sendo rápido o suficiente para passar por cima de instruções. Não sei o que causa isso, mas definir pontos de interrupção logo após as consultas do mongo evita isso.
Dan Dascalescu 26/09
76

Este erro ocorre porque o driver mongo interrompe a conexão por qualquer motivo (o servidor estava inativo, por exemplo).

Por padrão, o mangusto tentará se reconectar por 30 segundos, depois parará de tentar novamente e lançará erros para sempre até reiniciar.

Você pode alterar isso editando esses 2 campos nas opções de conexão

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

documentação das opções de conexão

gafi
fonte
3
Sim. Tecnicamente, a resposta aceita responde à pergunta, mas é o caminho certo para evitar o cenário em discussão.
kingdango
3
usando Mongo motorista a partir da versão 3.4.2, estas opções precisam estar no nível superior: opções: {keepAlive: 1, connectTimeoutMS: 30000, reconnectTries: 30, reconnectInterval: 2000}
Sebastien H.
1
Para esclarecer, de acordo com a documentação do driver Node MongoDB , por padrão, o servidor tentaria se reconectar 30 vezes, com um segundo de intervalo entre cada nova tentativa.
Boaz
4
Você não precisa fornecer essas opções no objeto servidor agora. Vai diretamente para os objetos de opções.
Animesh Singh
3
Só queria acrescentar que as versões recentes do mangusto ter essas opções em nível superior, então não há necessidade de adicionar server: {etc.
Alex K
17

No meu caso, esse erro foi causado por uma db.close();seção fora de 'aguardar' dentro 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
fonte
2
No caso de Carlos, acho que o fechamento aconteceu antes de tudo. Meu caso foi semelhante: acessei o banco de dados depois de fechá-lo. Seria bom se os desenvolvedores do Mongo pudessem produzir mensagens de erro mais explícitas. A "Topologia interrompida" soa como uma nota interna.
Juan Lanus
3
sua solução foi para mover o db.closeem um thenbloco, certo?
AlexChaffee
Está correto, no meu caso, apenas apago a linha db.close (), mas movo-a para um bloco then parece ser uma boa solução.
Carlos Rodríguez
1
Mover db.closepara um thenbloco funcionou muito bem para mim com o driver nativo do MongoDB Node.js.
precisa saber é o seguinte
12

Apenas uma pequena adição à resposta de Gaafar, isso me deu um aviso de reprovação. Em vez de no objeto do servidor, assim:

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

Pode ir no objeto de nível superior. Basicamente, basta retirá-lo do objeto servidor e colocá-lo no objeto de opções como este:

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

"A topologia foi destruída" pode ser causada pela desconexão do mangusto antes que os índices de documentos do mongo sejam criados, de acordo com este comentário

Para garantir que todos os modelos tenham seus índices criados antes de desconectar, você pode:

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

await mongoose.disconnect();
golfadas
fonte
obrigado, se você estiver executando casos de teste - esta é provavelmente uma resposta muito provável ...
Nick H247
1
Foi isso para mim. Obrigado! Eu estava executando testes no Jest com o mongodb-memory-server, obtendo erros esporádicos na topologia ou em identificadores abertos / promessas inacabadas. Mas às vezes funcionava. A adição de uma espera nos índices o corrigiu.
roblingle
Eu recebo esse erro sem o Mongoose, ao depurar o código Jest como @roblingle e não ser rápido o suficiente para passar por cima de instruções. Não sei o que causa isso, mas definir pontos de interrupção logo após as consultas do mongo evita isso.
Dan Dascalescu 26/09
@roblingle como você acabou corrigindo isso? Acabei de encontrar este problema e tornou impossível me conectar ao MongoDB novamente. Desde então, apaguei tudo e reinstalei o MongoDB (via homebrew) e agora não será mais executado na inicialização. (Pode ser uma questão não relacionada)
bobbyz
Parece não relacionado. Meu aplicativo funcionou bem, mas os testes falharam.
usar o seguinte comando
3

O comentário de Sebastian sobre a resposta de Adrien precisa de mais atenção, mas isso pode ser ignorado em algum momento, então aqui está uma solução :

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);
    }
});
Mamba negra
fonte
2

Eu também tive o mesmo erro. Finalmente, descobri que tenho algum erro no meu código. Uso o equilíbrio de carga para dois servidores nodejs, mas atualizo o código de um servidor.

Eu mudo meu servidor mongod from standalone to replication, mas esqueço de fazer a atualização correspondente para a cadeia de conexão, então encontrei este erro.

cadeia de conexão autônoma: mongodb://server-1:27017/mydb cadeia de conexão de replicação: mongodb://server-1:27017,server-2:27017,server-3:27017/mydb?replicaSet=myReplSet

detalhes aqui :[mongo doc para string de conexão]

lutaoact
fonte
2

Eu conheci isso no ambiente kubernetes / minikube + nodejs + mangusto. O problema era que o serviço DNS estava com um tipo de latência. A verificação do DNS está pronta resolveu o meu 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
};

(os números em db_options são arbitrários encontrados no stackoverflow e sites semelhantes)

tkrizsa
fonte
2

Aqui o que eu fiz, funciona bem. O problema desapareceu depois de adicionar as opções abaixo.

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

Você precisa reiniciar o mongo para resolver o erro de topologia e, em seguida, basta alterar algumas opções do mongoose ou mongoclient para superar esse problema:

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

mongoose.connect(mongoDevString,mongoOptions);
Ganesh sharma
fonte
Bem-vindo ao SO! Por favor edite sua resposta e adicionar mais algumas informações, ou seja, como ele resolve o problema, por mais orientação ver stackoverflow.com/help/how-to-ask
B - Rian
1

Eu recebi esse erro enquanto criava um novo banco de dados na minha comunidade do MongoDb Compass. O problema estava no meu Mongod, ele não estava em execução. Portanto, como correção, tive que executar o comando Mongod como anterior.

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

Consegui criar um banco de dados depois de executar esse comando.

Espero que ajude.

Sibeesh Venu
fonte
1

Eu estava lutando com isso há algum tempo - Como você pode ver em outras respostas, o problema pode ser muito diferente.

A maneira mais fácil de descobrir o que está causando é ativar loggerLevel: 'info'as opções

orepor
fonte
0

No meu caso, esse erro foi causado por uma instância de servidor idêntica já em execução em segundo plano.

O estranho é que, quando iniciei meu servidor sem aviso prévio, já havia um em execução, o console não mostrava nada como 'algo está usando a porta xxx'. Eu poderia até enviar algo para o servidor. Então, demorei bastante para localizar esse problema.

Além do mais, depois de fechar todos os aplicativos que consigo imaginar, ainda não consegui encontrar o processo que está usando essa porta no monitor de atividades do meu Mac. Eu tenho que usar lsofpara rastrear. O culpado não foi surpreendente - é um processo de nó. No entanto, com o PID mostrado no terminal, descobri que o número da porta no monitor é diferente daquele usado pelo meu servidor.

Em suma, matar todos os processos do nó pode resolver esse problema diretamente.

AnLuoRidge
fonte
-3

Resolvi esse problema:

  1. garantindo que o mongo esteja em execução
  2. reiniciando meu servidor
maia
fonte
4
Isso não impede que o problema ocorra novamente
Sam Munroe