mongoError: Топологія була знищена


163

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

Вчора раптом вузол почав викривляти помилки із повідомленням "MongoError: Топологія була знищена", більше нічого. Я поняття не маю, що мається на увазі під цим і що, можливо, могло це викликати. Google також не може бути знайдений під час пошуку в Google. Тому я думав, що запитаю тут.

Після перезапуску служби вузла сьогодні помилки перестали надходити. У мене також є одна з цих функцій у виробництві, і мене лякає, що це може статися в будь-який момент досить важливої ​​частини налаштування, що працює там ...

Я використовую наступні версії згаданих пакетів:

  • мангуст: 4.0.3
  • відхилити: 3.0.3
  • вузол: 0.10.25

2
У мене є подібні проблеми з використанням лише драйвера mongodb :(
0x8890

1
Я не використовую вітрила, так що ні, я не думаю, що це вирішить мою проблему
dreagan

Відповіді:


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

Це, мабуть, не пов’язане з проблемою "Вітрила", процитованою в коментарях, оскільки не було встановлено оновлень, щоб запобігти краху або "виправити"


2
У мене те саме питання, і це трапляється майже щотижня і вимикає програму, яка працює з монго, це якась проблема, яку я створив, чи це проблема в мангусті?
Мохаммед Ганжі

@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, повторно підключенняTries: 30, повторно підключенняInterval: 5000}
Sebastien H.

Я отримую цю помилку без Mongoose, одночасно налагоджуючи код клієнта і не досить швидко переходячи через оператори. Не впевнений, що це викликає, але встановлення точок перерви відразу після запитів монго уникає цього.
Дан Даскалеску

76

Ця помилка пояснюється тим, що драйвер mongo перервав з'єднання з будь-якої причини (наприклад, сервер був відключений).

За замовчуванням мангуст намагатиметься знову підключитися на 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 
        } 
    }
);

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


3
Так. Технічно прийнята відповідь відповідає на поставлене питання, Але це правильний спосіб уникнути обговорюваного сценарію.
kingdango

3
використовуючи драйвер Mongo з версії 3.4.2, ці параметри повинні бути на найвищому рівні: параметри: {KeepAlive: 1, connectTimeoutMS: 30000, повторно з'єднатиСпроби: 30, знову підключитиІнтервал: 2000}
Себастьян Х.

1
Для уточнення, згідно з документацією драйвера Node MongoDB , за замовчуванням сервер намагатиметься повторно підключитися 30 разів, з розрізом однієї секунди між кожним спробою.
Боаз

4
Зараз вам не потрібно вказувати ці параметри під об’єктом сервера. Він прямує до об'єктів опцій.
Анімеш Сінгх

3
Просто хотів додати, що останні версії мангуста мають ці параметри на найвищому рівні, тому не потрібно додавати 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 (), але переміщувати її в блок тоді здається гарним рішенням.
Карлос Родрігес

1
Переміщення db.closeдо thenблоку чудово працювало для мене з рідним драйвером MongoDB Node.js.
kevinmicke

12

Лише незначне доповнення до відповіді Гаафара, воно дало мені попередження про депресію. Замість об’єкта на сервері, як це:

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

Він може перейти на об'єкт верхнього рівня. В основному, просто вийміть його з серверного об'єкта і помістіть його в такий об'єкт параметрів:

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

7

"Топологія була знищена" може бути викликана відключенням мангуста до того, як будуть створені індекси документів mongo, відповідно до цього коментаря

Для того, щоб переконатися, що всі моделі мають вбудовані індекси перед відключенням, ви можете:

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

await mongoose.disconnect();

дякую, якщо ви
ведете

1
Це було для мене. Дякую! Я проводив тести в Jest з сервером mongodb-memory, отримуючи спорадичні помилки в топології або відкриті ручки / незакінчені обіцянки. Але іноді це спрацювало. Додавання очікування на індекси виправлено.
roblingle

Я отримую цю помилку без Mongoose, одночасно налагоджуючи Jest-код, наприклад, @roblingle і не будучи досить швидким при переході на оператори. Не впевнений, що це викликає, але встановлення точок перерви відразу після запитів монго уникає цього.
Дан Даскалеску

@roblingle як ти закінчив це виправити? Я просто зіткнувся з цією проблемою, і це зробило неможливим знову підключитися до MongoDB. З тих пір я все видалив і перевстановив MongoDB (через homebrew), і тепер він більше не запускається при запуску. (Може бути непов'язане питання)
bobbyz

Звуки не пов’язані між собою. Моя програма працювала чудово, але тести не вдається.
roblingle

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 for string string]


2

Я зустрів це в середовищі kubernetes / minikube + nodejs + мангуста. Проблема полягала в тому, що служба 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 довільно знаходять на stackoverflow та подібних сайтах)


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

});

2

Вам потрібно перезапустити монго, щоб вирішити помилку топології, а потім просто змінити деякі параметри мангуста або монгокліента, щоб подолати цю проблему:

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

mongoose.connect(mongoDevString,mongoOptions);

Ласкаво просимо до SO! Будь ласка редагувати свою відповідь і додати більше інформації, тобто , як вона вирішує цю проблему, для більш інструктивного см stackoverflow.com/help/how-to-ask
B - РИАН

1

Я отримав цю помилку під час створення нової бази даних у моїй спільноті MongoDb Compass. Проблема була з моїм монгодом, вона не працювала. Отже, як виправлення, мені довелося виконати команду Mongod, як і раніше.

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

Мені вдалося створити базу даних після запуску цієї команди.

Сподіваюся, це допомагає.


1

Я певний час боровся з цим - Як видно з інших відповідей, питання може бути дуже різним.

Найпростіший спосіб з'ясувати, що викликає, це ввімкнути loggerLevel: 'info'параметри


0

У моєму випадку ця помилка була викликана ідентичним екземпляром сервера, який вже працює у фоновому режимі.

Дивна річ, коли я запустив свій сервер без попереднього повідомлення, там вже працює один, консоль нічого не показує, як "щось використовується порт xxx". Я навіть міг щось завантажити на сервер. Отже, мені знадобилося досить багато часу, щоб знайти цю проблему.

Більше того, після закриття всіх програм, які я можу собі уявити, я все ще не зміг знайти процес, який використовує цей порт у моніторі діяльності мого Mac. Мені доводиться використовувати lsofтрасування. Винуватець не дивувався - це процес вузла. Однак, показавши PID в терміналі, я виявив, що номер порту в моніторі відрізняється від того, який використовує мій сервер.

Загалом, вбити всі вузлові процеси можуть безпосередньо вирішити цю проблему.


-3

Я вирішив це питання:

  1. забезпечення роботи монго
  2. перезапуск мого сервера

4
Це не заважає проблемі повторитися
Сем Манро
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.