mongoError: Топология уничтожена

163

У меня есть служба REST, встроенная в node.js с Restify и Mongoose, и mongoDB с коллекцией, содержащей около 30 000 документов обычного размера. У меня есть служба узла, работающая через pmx и pm2.

Вчера, внезапно, узел начал выводить сообщения об ошибках с сообщением «MongoError: Топология была уничтожена», не более того. Я понятия не имею, что подразумевается под этим и что, возможно, могло вызвать это. при поиске в Google это тоже не так много. Поэтому я решил спросить здесь.

После перезапуска службы узла сегодня ошибки перестали поступать. У меня также есть одна из них, запущенная в работе, и она пугает меня, что это может произойти в любой момент с довольно важной частью выполняемой там установки ...

Я использую следующие версии упомянутых пакетов:

  • мангуст: 4.0.3
  • restify: 3.0.3
  • узел: 0.10.25
dreagan
источник
2
У меня похожие проблемы с использованием только драйвера mongodb :(
0x8890
1
Я не использую паруса, поэтому нет, я не думаю, что это
решило

Ответы:

98

Кажется, это означает, что соединение вашего нод-сервера с вашим экземпляром MongoDB было прервано во время попытки записи в него.

Взгляните на исходный код Mongo, который генерирует эту ошибку

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

Похоже, это не связано с проблемой Sails, упомянутой в комментариях, так как не было установлено никаких обновлений, чтобы ускорить сбой или «исправить»

Джейсон Николс
источник
2
У меня та же проблема, и это происходит почти каждую неделю и закрывает приложение, работающее с mongo. Это какая-то проблема, сгенерированная мной, или это проблема в mongoose?
Мохаммад Ганджи
@MohammadGanji: я получаю эту ошибку без Mongoose, пока отлаживаю код клиента и недостаточно быстро перехожу через операторы. Не уверен, с чем это связано, но установка точек останова сразу после монго-запросов позволяет избежать этого.
Дан Даскалеску
@DanDascalescu Я забыл упомянуть, что моя проблема была решена, это была проблема с журналированием, похоже, в журналах было какое-то предупреждение, которое через некоторое время занимало около гигабайта памяти и закрывало процесс Монго, поэтому я попытался выполнить архивирование и резервное копирование и проблема решена
Мухаммед Ганджи
83

Я знаю, что ответ Джейсона был принят, но у меня была та же проблема с Mongoose, и я обнаружил, что служба, поддерживающая мою базу данных, рекомендовала применить следующие параметры , чтобы поддерживать соединение Mongodb в рабочем состоянии:

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

Я надеюсь, что этот ответ может помочь другим людям с ошибками «Топология была уничтожена».

Адриен Джоли
источник
4
Это не решило проблему для меня. Я фактически увеличил свой keepAlive до 30000, что очень помогло. Даже при том, что я все еще получаю случайную ошибку топологии.
ifightcrime
9
При использовании драйвера Mongo из версии 3.4.2 эти параметры должны быть на верхнем уровне: параметры: {keepAlive: 1, connectTimeoutMS: 30000, reinnectTries: 30, reconnectInterval: 5000}
Себастьен Х.
Я получаю эту ошибку без Mongoose, когда отлаживаю код клиента и недостаточно быстро перехожу через операторы. Не уверен, с чем это связано, но установка точек останова сразу после монго-запросов позволяет избежать этого.
Дан Даскалеску
76

Эта ошибка происходит из-за того, что драйвер Монго разорвал соединение по любой причине (например, сервер не работал).

По умолчанию мангуста будет пытаться восстановить соединение в течение 30 секунд, затем прекратит повторную попытку и выкинет ошибки навсегда до перезапуска.

Вы можете изменить это, отредактировав эти 2 поля в настройках подключения

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

документация по вариантам подключения

GAFI
источник
3
Ага. Технически принятый ответ отвечает на заданный вопрос, НО это верный способ избежать обсуждаемого сценария.
кингданго
3
используя драйвер Mongo версии 3.4.2, эти параметры должны быть на верхнем уровне: параметры: {keepAlive: 1, connectTimeoutMS: 30000, reinnectTries: 30, reconnectInterval: 2000}
Себастьен Х.
1
Для пояснения, согласно документации драйвера Node MongoDB , по умолчанию сервер будет пытаться восстановить соединение 30 раз с интервалом в одну секунду между каждой попыткой.
Вооз
4
Вам не нужно предоставлять эти опции в объекте сервера сейчас. Он идет прямо к опциям объектов.
Анимеш Сингх
3
Просто хотел добавить, что в последних версиях mongoose эти параметры находятся на верхнем уровне, поэтому добавлять их не нужно и server: {т. Д.
Alex K
17

В моем случае эта ошибка была вызвана db.close();разделом «ожидание» внутри «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
В случае с Карлосом, я думаю, близость произошла раньше, чем все остальное. Мой случай был похож: я получил доступ к БД после ее закрытия. Было бы хорошо, если бы разработчики Mongo могли выдавать более явные сообщения об ошибках. «Топология нарушена» звучит как внутренняя нота.
Хуан Ланус
3
Ваше решение было переместить db.closeв thenблок, верно?
AlexChaffee
Это правильно, в моем случае я только удаляю строку db.close (), но перемещаю ее в блок then, что кажется хорошим решением.
Карлос Родригес
1
Перемещение db.closeк thenблоку работал большим для меня с родным драйвером MongoDB Node.js.
Кевинмике
12

Просто незначительное дополнение к ответу Гаафара, это дало мне предупреждение об устаревании. Вместо объекта на сервере, вот так:

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

Это может пойти на объекте верхнего уровня. По сути, просто извлеките его из объекта сервера и поместите в объект параметров следующим образом:

MongoClient.connect(MONGO_URL, {
    reconnectTries: Number.MAX_VALUE,
    reconnectInterval: 1000
});
codeinaire
источник
7

«Топология была уничтожена» может быть вызвано отключением mongoose перед созданием индексов документов mongo, согласно этому комментарию

Чтобы убедиться, что все модели имеют свои индексы, построенные перед отключением, вы можете:

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

await mongoose.disconnect();
golfadas
источник
спасибо, если вы запускаете тестовые случаи - это, вероятно, очень вероятный ответ ...
Ник H247
1
Это было для меня. Спасибо! Я проводил тесты в Jest с mongodb-memory-server, получая отдельные ошибки в топологии или открытые дескрипторы / незаконченные обещания. Но иногда это работало. Добавление ожидания на индексы исправило это.
Роблингл
Я получаю эту ошибку без Mongoose, отлаживая Jest-код, такой как @roblingle, и недостаточно быстро перебирая операторы. Не уверен, с чем это связано, но установка точек останова сразу после монго-запросов позволяет избежать этого.
Дан Даскалеску
@roblingle как ты в итоге это исправил? Я только столкнулся с этой проблемой, и я не смог снова подключиться к MongoDB. С тех пор я удалил все и переустановил MongoDB (через homebrew), и теперь он больше не запускается при запуске. (Может быть, не связанная с этим проблема)
bobbyz
Звучит не связано. Мое приложение работало нормально, но тесты не пройдены.
Роблингл
3

Комментарий Себастьяна к ответу Адриена требует большего внимания, это помогло мне, но этот комментарий может быть проигнорирован, так что вот решение :

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

У меня тоже была такая же ошибка. Наконец, я обнаружил, что у меня есть ошибка в моем коде. Я использую балансировку нагрузки для двух серверов nodejs, но я просто обновляю код одного сервера.

Я меняю свой сервер mongod from standalone to replication, но забываю сделать соответствующее обновление для строки подключения, поэтому я встретил эту ошибку.

строка автономного подключения: mongodb://server-1:27017/mydb строка подключения репликации: mongodb://server-1:27017,server-2:27017,server-3:27017/mydb?replicaSet=myReplSet

подробности здесь: [Mongo Doc для строки подключения]

lutaoact
источник
2

Я встречал это в среде kubernetes / minikube + nodejs + mongoose. Проблема заключалась в том, что служба DNS работала с некоторой задержкой. Проверка DNS готова решить мою проблему.

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

(числа в db_options произвольно найдены на стековом потоке и подобных сайтах)

tkrizsa
источник
2

Вот что я сделал, работает отлично. Проблема исчезла после добавления ниже вариантов.

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
источник
2

Вам нужно перезапустить mongo, чтобы решить ошибку топологии, а затем просто изменить некоторые параметры mongoose или mongoclient, чтобы преодолеть эту проблему:

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

mongoose.connect(mongoDevString,mongoOptions);
Ганеш Шарма
источник
Добро пожаловать на ТАК! Пожалуйста, отредактируйте свой ответ и добавьте дополнительную информацию, например, как она решает проблему, для получения дополнительной информации см. Stackoverflow.com/help/how-to-ask
B -
1

Я получил эту ошибку, когда создавал новую базу данных в сообществе MongoDb Compass. Проблема была с моим Mongod, он не работал. В качестве исправления я должен был выполнить команду Mongod, как описано выше.

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

Я смог создать базу данных после выполнения этой команды.

Надеюсь, поможет.

Сибееш Вену
источник
1

Я боролся с этим в течение некоторого времени - как вы можете видеть из других ответов, проблема может быть совсем другой.

Самый простой способ выяснить, что является причиной этого, это включить loggerLevel: 'info'в настройках

orepor
источник
0

В моем случае эта ошибка была вызвана тем же экземпляром сервера, который уже работал в фоновом режиме.

Странно то, что когда я запустил свой сервер без предварительного уведомления, он уже запущен, консоль не показала ничего вроде «что-то использует порт xxx». Я мог бы даже загрузить что-то на сервер. Итак, мне потребовалось довольно много времени, чтобы найти эту проблему.

Более того, после закрытия всех приложений, которые я могу себе представить, я все еще не мог найти процесс, использующий этот порт, в мониторе активности моего Mac. Я должен использоватьlsof для отслеживания. Виновник не был удивительным - это процесс узла. Однако с помощью идентификатора PID, показанного в терминале, я обнаружил, что номер порта на мониторе отличается от номера порта, используемого моим сервером.

В общем, уничтожение всех процессов узла может решить эту проблему напрямую.

AnLuoRidge
источник
-3

Я решил эту проблему:

  1. обеспечение работы монго
  2. перезапуск моего сервера
Maia
источник
4
Это не препятствует повторению проблемы
Сэм Манро,