mongoError: Topologi hancur

163

Saya memiliki layanan REST yang dibangun di node.js dengan Restify dan Mongoose dan mongoDB dengan koleksi dengan sekitar 30.000 dokumen berukuran biasa. Saya memiliki layanan simpul saya berjalan melalui pmx dan pm2.

Kemarin, tiba-tiba, node mulai menyelesaikan kesalahan dengan pesan "MongoError: Topology dihancurkan", tidak lebih. Saya tidak tahu apa yang dimaksud dengan ini dan apa yang mungkin memicu ini. ada juga tidak banyak yang bisa ditemukan ketika google mencari ini. Jadi saya pikir saya akan bertanya di sini.

Setelah memulai kembali layanan simpul hari ini, kesalahan berhenti datang. Saya juga memiliki salah satu dari ini berjalan dalam produksi dan itu membuat saya takut bahwa ini bisa terjadi pada waktu tertentu ke bagian yang sangat penting dari pengaturan yang berjalan di sana ...

Saya menggunakan versi berikut dari paket-paket yang disebutkan:

  • luwak: 4.0.3
  • restify: 3.0.3
  • simpul: 0.10.25
dreagan
sumber
2
Saya mengalami masalah serupa hanya menggunakan driver mongodb :(
0x8890
1
Saya tidak menggunakan layar, jadi tidak, saya tidak berpikir itu akan memperbaiki masalah saya
dreagan

Jawaban:

98

Tampaknya ini berarti koneksi server node Anda ke instance MongoDB Anda terputus ketika sedang mencoba untuk menulisnya.

Lihatlah kode sumber Mongo yang menghasilkan kesalahan itu

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

Ini tampaknya tidak terkait dengan masalah Sails yang dikutip dalam komentar, karena tidak ada pemutakhiran yang dipasang untuk mempercepat crash atau "perbaikan"

Jason Nichols
sumber
2
Saya memiliki masalah yang sama dan ini terjadi hampir setiap minggu dan mematikan aplikasi yang bekerja dengan mongo, apakah ini beberapa masalah yang saya hasilkan atau ini masalah dalam luwak?
Mohammad Ganji
@MohammadGanji: Saya mendapatkan kesalahan ini tanpa Mongoose, saat debugging kode klien dan tidak cukup cepat dalam melangkahi pernyataan. Tidak yakin apa yang menyebabkannya, tetapi pengaturan breakpoints tepat setelah mongo queries menghindarinya.
Dan Dascalescu
@DanDascalescu Saya lupa menyebutkan bahwa masalah saya telah dipecahkan, itu adalah masalah dengan logging, sepertinya ada beberapa peringatan dalam log yang setelah beberapa saat mengambil sekitar satu gigabyte penyimpanan dan mematikan proses mongo, jadi saya mencoba zipping dan mencadangkan dan masalah terpecahkan
Mohammad Ganji
83

Saya tahu bahwa jawaban Jason diterima, tetapi saya memiliki masalah yang sama dengan Mongoose dan menemukan bahwa layanan hosting database saya merekomendasikan untuk menerapkan pengaturan berikut untuk menjaga koneksi Mongodb tetap dalam produksi:

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

Saya harap balasan ini dapat membantu orang lain yang memiliki kesalahan "Topologi dihancurkan".

Adrien Joly
sumber
4
Ini tidak memperbaiki masalah bagi saya. Saya akhirnya meningkatkan keepAlive saya ke 30000, yang telah sangat membantu. Meskipun saya masih mendapatkan kesalahan topologi sesekali datang masih.
ifightcrime
9
menggunakan driver Mongo dari versi 3.4.2, opsi ini harus berada di tingkat atas: opsi: {keepAlive: 1, connectTimeoutMS: 30000, hubungkan kembali Coba: 30, hubungkan kembaliInterval: 5000}
Sebastien H.
Saya mendapatkan kesalahan ini tanpa Mongoose, sambil men-debug kode klien dan tidak cukup cepat dalam melangkahi pernyataan. Tidak yakin apa yang menyebabkannya, tetapi pengaturan breakpoints tepat setelah mongo queries menghindarinya.
Dan Dascalescu
76

Kesalahan ini disebabkan oleh driver mongo yang menjatuhkan koneksi dengan alasan apa pun (server terputus misalnya).

Secara default luwak akan mencoba untuk menyambung kembali selama 30 detik kemudian berhenti mencoba lagi dan melemparkan kesalahan selamanya sampai dimulai kembali.

Anda dapat mengubah ini dengan mengedit 2 bidang ini di opsi koneksi

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

dokumentasi opsi koneksi

Gafi
sumber
3
Ya. Secara teknis jawaban yang diterima menjawab pertanyaan yang TETAPI ini adalah cara yang tepat untuk menghindari skenario yang sedang dibahas.
kingdango
3
menggunakan driver Mongo dari versi 3.4.2, opsi ini harus berada di tingkat atas: opsi: {keepAlive: 1, connectTimeoutMS: 30000, hubungkan kembali Coba: 30, hubungkan kembaliInterval: 2000}
Sebastien H.
1
Untuk memperjelas, menurut dokumentasi Driver Node MongoDB , secara default server akan mencoba untuk menyambung kembali 30 kali, dengan satu detik terpisah antara setiap coba lagi.
Boaz
4
Anda tidak perlu memberikan opsi ini di bawah objek server sekarang. Langsung ke objek opsi.
Animesh Singh
3
Hanya ingin menambahkan bahwa versi luwak terbaru memiliki opsi-opsi itu di tingkat atas, jadi tidak perlu menambahkan server: {dll.
Alex K
17

Dalam kasus saya, kesalahan ini disebabkan oleh db.close();bagian 'menunggu' di dalam '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
sumber
2
Dalam kasus Carlos, saya kira penutupan terjadi sebelum yang lainnya. Kasus saya serupa: Saya mengakses DB setelah menutupnya. Alangkah baiknya jika pengembang Mongo dapat menghasilkan pesan kesalahan yang lebih eksplisit. "Topologi patah" terdengar seperti nada internal.
Juan Lanus
3
solusi Anda adalah memindahkannya db.closeke dalam thenblok, bukan?
AlexChaffee
Itu benar, dalam kasus saya, saya hanya menghapus baris db.close (), tetapi memindahkannya ke blok maka tampaknya menjadi solusi yang bagus.
Carlos Rodríguez
1
Memindahkan db.closeke thenblok bekerja sangat baik untuk saya dengan driver Node.js MongoDB asli.
kevinmicke
12

Hanya sedikit tambahan untuk jawaban Gaafar, itu memberi saya peringatan penghinaan. Alih-alih pada objek server, seperti ini:

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

Itu bisa pergi pada objek tingkat atas. Pada dasarnya, keluarkan saja dari objek server dan letakkan di objek opsi seperti ini:

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

"Topologi dihancurkan" mungkin disebabkan oleh pemutusan luwak sebelum indeks dokumen luong dibuat, per komentar ini

Untuk memastikan semua model memiliki indeks yang dibangun sebelum memutuskan sambungan, Anda dapat:

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

await mongoose.disconnect();
golfada
sumber
terima kasih, jika Anda menjalankan test case - ini mungkin jawaban yang sangat mungkin ...
Nick H247
1
Ini untuk saya. Terima kasih! Saya menjalankan tes di Jest dengan mongodb-memory-server, mendapatkan kesalahan sporadis pada topologi atau menangani terbuka / Janji yang belum selesai. Tapi terkadang itu berhasil. Menambahkan menunggu pada indeks memperbaikinya.
Roblingle
Saya mendapatkan kesalahan ini tanpa Mongoose, sementara debug kode Jest seperti @roblingle dan tidak cukup cepat dalam melangkahi pernyataan. Tidak yakin apa yang menyebabkannya, tetapi pengaturan breakpoints tepat setelah mongo queries menghindarinya.
Dan Dascalescu
@roblingle bagaimana akhirnya Anda memperbaikinya? Saya hanya mengalami masalah ini dan itu membuat saya tidak mungkin terhubung ke MongoDB lagi. Sejak itu saya telah menghapus semuanya dan menginstal ulang MongoDB (via homebrew) dan sekarang tidak akan berjalan saat startup lagi. (Mungkin masalah yang tidak terkait)
bobbyz
Kedengarannya tidak berhubungan. Aplikasi saya berfungsi dengan baik tetapi tes gagal.
Roblingle
3

Sebastian mengomentari jawaban Adrien membutuhkan lebih banyak perhatian, itu membantu saya, tetapi menjadi komentar mungkin diabaikan kadang-kadang jadi ini solusinya :

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 hitam
sumber
2

Saya juga memiliki kesalahan yang sama. Akhirnya, saya menemukan bahwa saya memiliki beberapa kesalahan pada kode saya. Saya menggunakan load balance untuk dua nodejs server, tetapi saya hanya memperbarui kode satu server.

Saya mengubah server mongod saya from standalone to replication , tetapi saya lupa untuk melakukan pembaruan yang sesuai untuk string koneksi, jadi saya menemukan kesalahan ini.

string koneksi mandiri: mongodb://server-1:27017/mydb string koneksi replikasi: mongodb://server-1:27017,server-2:27017,server-3:27017/mydb?replicaSet=myReplSet

detail di sini :[mongo doc untuk string koneksi]

lutaoact
sumber
2

Saya bertemu ini di kubernetes / minikube + nodejs + luwak. Masalahnya adalah bahwa layanan DNS dengan semacam latensi. Memeriksa DNS siap menyelesaikan masalah saya.

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

(angka-angka dalam db_options ditemukan secara sewenang-wenang di stackoverflow dan situs sejenisnya)

tkrizsa
sumber
2

Di sini apa yang saya lakukan, itu berfungsi dengan baik. Masalah hilang setelah menambahkan opsi di bawah ini.

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

Anda perlu me-restart mongo untuk menyelesaikan kesalahan topologi, lalu cukup mengubah beberapa opsi luong atau mongoclient untuk mengatasi masalah ini:

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

mongoose.connect(mongoDevString,mongoOptions);
Ganesh sharma
sumber
Selamat datang di SO! Harap edit jawaban Anda dan tambahkan beberapa informasi lebih lanjut, yaitu cara memecahkan masalah, untuk panduan lebih lanjut, lihat stackoverflow.com/help/how-to-ask
B - rian
1

Saya mendapatkan kesalahan ini, ketika saya sedang membuat database baru di Komunitas Kompas MongoDb saya. Masalahnya adalah dengan Mongod saya, itu tidak berjalan. Jadi sebagai perbaikan, saya harus menjalankan perintah Mongod seperti sebelumnya.

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

Saya bisa membuat database setelah menjalankan perintah itu.

Semoga ini bisa membantu.

Sibeesh Venu
sumber
1

Saya berjuang dengan ini selama beberapa waktu - Seperti yang Anda lihat dari jawaban lain, masalahnya bisa sangat berbeda.

Cara termudah untuk mengetahui apa yang menyebabkannya adalah dengan mengaktifkan loggerLevel: 'info'opsi

orepor
sumber
0

Dalam kasus saya, kesalahan ini disebabkan oleh contoh server identik yang sudah berjalan latar belakang.

Yang aneh adalah ketika saya memulai server saya tanpa pemberitahuan sudah ada yang berjalan, konsol tidak menunjukkan sesuatu seperti 'sesuatu menggunakan port xxx'. Saya bahkan dapat mengunggah sesuatu ke server. Jadi, butuh waktu cukup lama untuk menemukan masalah ini.

Terlebih lagi, setelah menutup semua aplikasi yang dapat saya bayangkan, saya masih tidak dapat menemukan proses yang menggunakan port ini di monitor aktivitas Mac saya. Saya harus menggunakanlsof untuk melacak. Pelakunya tidak mengejutkan - ini adalah proses simpul. Namun, dengan PID yang ditampilkan di terminal, saya menemukan nomor port di monitor berbeda dari yang digunakan oleh server saya.

Semua dalam semua, membunuh semua proses simpul dapat menyelesaikan masalah ini secara langsung.

AnLuoRidge
sumber
-3

Saya memecahkan masalah ini dengan:

  1. memastikan mongo sedang berjalan
  2. restart server saya
maia
sumber
4
Ini tidak mencegah masalah terjadi lagi
Sam Munroe