Mongoose: Tidak ada percobaan ulang yang dilakukan setelah "gagal terhubung pada koneksi pertama"

Dibuat pada 17 Apr 2017  ·  40Komentar  ·  Sumber: Automattic/mongoose

Secara default, luwak melempar Kesalahan jika koneksi pertama gagal, yang membuat node crash.

Jadi untuk mereproduksi bug ini, Anda memerlukan kode berikut di aplikasi Anda, untuk menangkap kesalahan dan mencegah kerusakan:

db.on('error', console.error.bind(console, 'connection error:'));

Sekarang kita dapat mereproduksi bug ini sebagai berikut:

  1. Matikan MongoDB Anda
  2. Mulai aplikasi simpul Anda yang menggunakan luwak
  3. Aplikasi Anda akan mencatat: [MongoError: failed to connect to server [localhost:27017] on first connect [MongoError: connect ECONNREFUSED 127.0.0.1:27017]]
  4. Mulai MongoDB Anda lagi
  5. Perhatikan bahwa luwak sekarang tidak terhubung ke MongoDB yang berfungsi. Satu-satunya cara untuk terhubung kembali adalah dengan memulai ulang aplikasi Anda, atau menggunakan solusi manual .

Perilaku yang diharapkan: Karena autoreconnect default ke true, saya berharap luwak membuat koneksi segera setelah MongoDB dapat diakses kembali.

Catatan: Jika koneksi pertama berhasil, tetapi koneksi ke MongoDB terputus selama runtime, maka koneksi ulang otomatis berfungsi dengan baik, seperti yang diharapkan. Masalahnya adalah inkonsistensi jika MongoDB tidak tersedia saat aplikasi dijalankan.

(Jika ini adalah perilaku yang diinginkan, dan pengembang disarankan untuk menangani situasi ini dengan tidak menangkap kesalahan, dan membiarkan node mogok, maka saya dapat menerimanya, tetapi perlu dijelaskan.)

simpul v4.4.1, [email protected] , [email protected] , [email protected]

docs

Komentar yang paling membantu

Bagi siapa pun yang menginginkan koneksi ulang otomatis ketika koneksi pertama gagal, ini adalah cara saya menanganinya:

function createConnection (dbURL, options) {
    var db = mongoose.createConnection(dbURL, options);

    db.on('error', function (err) {
        // If first connect fails because mongod is down, try again later.
        // This is only needed for first connect, not for runtime reconnects.
        // See: https://github.com/Automattic/mongoose/issues/5169
        if (err.message && err.message.match(/failed to connect to server .* on first connect/)) {
            console.log(new Date(), String(err));

            // Wait for a bit, then try to connect again
            setTimeout(function () {
                console.log("Retrying first connect...");
                db.openUri(dbURL).catch(() => {});
                // Why the empty catch?
                // Well, errors thrown by db.open() will also be passed to .on('error'),
                // so we can handle them there, no need to log anything in the catch here.
                // But we still need this empty catch to avoid unhandled rejections.
            }, 20 * 1000);
        } else {
            // Some other error occurred.  Log it.
            console.error(new Date(), String(err));
        }
    });

    db.once('open', function () {
        console.log("Connection to db established.");
    });

    return db;
}

// Use it like
var db = createConnection('mongodb://...', options);
var User = db.model('User', userSchema);

Untuk luwak < 4.11 gunakan db.open() sebagai ganti db.openUri()
Untuk luwak 4.11.7 teknik ini tidak bekerja.
Untuk luwak 4.13.4 ini berfungsi lagi!


Sunting 2019/09/02: Ada juga solusi yang lebih pendek menggunakan promiseRetry sini .

Semua 40 komentar

dapat mengkonfirmasi.
simpul 6, 7, luwak (setidaknya 6 bulan), luwak 3.2 - 3.4
datang bersama dengan yang ini #4890

saya kira ini adalah masalah mongodb-core . Itu harus mencoba untuk menyambung kembali bahkan jika percobaan pertama gagal, saya pikir, karena saya tidak yakin mengapa itu akan berbeda dari upaya berikutnya.

Bisakah Anda juga melaporkan masalah ini di sana?

Berikut skrip repro lengkap:

const mongoose = require('mongoose');
const co = require('co');
mongoose.Promise = global.Promise;
const GITHUB_ISSUE = `gh-5169`;


exec()
  .catch(error => {
    console.error(`Error: ${ error }\n${ error.stack }`);
  });


function exec() {
  return co(function*() {
    const db = mongoose.createConnection(`mongodb://localhost:27017/${ GITHUB_ISSUE }`);
    db.on('error', (error) => {
      console.error(`in an error ${ error }\n${ error.stack }`);
    })
  });
}

Terima kasih atas repronya. Saya telah melihat ke mongodb-core. Ini adalah perilaku yang dimaksudkan pengemudi :

Driver akan gagal pada koneksi pertama jika tidak dapat terhubung ke host. Ini dirancang untuk memastikan kegagalan cepat pada host yang tidak dapat dijangkau. Perilaku menyambungkan kembali hanya muncul setelah pengemudi melakukan koneksi awal.

Terserah aplikasi untuk memutuskan apa yang harus dilakukan. Ini dirancang untuk memastikan pengemudi gagal dengan cepat dan tidak duduk di sana membuat Anda berpikir itu benar-benar berfungsi.

Jadi saya curiga kita tidak akan mendapatkan perilaku yang berbeda dari pengemudi.

Saya sebenarnya berpikir bahwa perilaku itu masuk akal untuk pengemudi tingkat rendah. Ini akan membantu pengembang yang secara tidak sengaja mencoba terhubung ke host yang salah atau port yang salah.

Tetapi jika kami ingin melakukan sesuatu yang lebih ramah pengembang di luwak, kami dapat mempertimbangkan:

  • Saat opsi sambung ulang otomatis diaktifkan, terus coba sambungkan kembali hingga server Mongo dapat dihubungi (dengan membangun sesuatu seperti solusi yang ditautkan di atas).
  • Log ketika luwak melakukan ini, jadi dalam kasus koneksi yang tidak pernah dibuat, pengembang setidaknya akan tahu di mana masalahnya.
    (Log dapat ditunda, misalnya 30 detik. Sebenarnya alih-alih logging langsung, saya kira kita harus mengeluarkan acara error penasehat, tetapi tetap mencoba menyambungkan kembali secara otomatis.)

Jika saya ingat dengan benar, ketika saya menggunakan solusi dan akhirnya terhubung setelah beberapa upaya gagal, kueri yang sudah diantrekan oleh aplikasi memang dieksekusi seperti yang diinginkan. (Tapi ini layak untuk diuji lagi.)

saya pikir ini adalah ide yang bagus sebenarnya, saya akan melabeli ini sebagai permintaan fitur

Tidak, gagal cepat pada koneksi awal adalah perilaku yang cukup konsisten di seluruh driver MongoDB dan tidak banyak manfaat untuk mendukung luwak.

Posting terbaru dari konektor mongodb Strongloop Loopback ini mungkin relevan. Bendera lazyConnect menunda koneksi pertama hingga titik akhir tercapai. Jika koneksi pertama gagal dalam kasus itu, pengaturan kehilangan koneksi default akan berlaku (akan mencoba lagi).

Minat saya adalah orkestrasi wadah, di mana "pesanan startup wadah" sering dapat diatur dan diharapkan tetapi "pesanan ketersediaan layanan" tidak bisa. Alat orkestrasi mungkin mengonfirmasi bahwa wadah mongo "naik" meskipun layanan mongo belum tersedia.

Jadi, jika wadah mongo saya membutuhkan waktu 1 detik untuk memulai tetapi 5 detik untuk layanan tersedia, dan wadah aplikasi saya membutuhkan 1 detik untuk memulai dan 1 detik untuk layanan tersedia, layanan aplikasi akan berlari lebih cepat dari layanan mongo, menyebabkan kegagalan koneksi pertama seperti yang awalnya dijelaskan .

Dokumentasi Docker Compose mengatakan ini:

Compose tidak akan menunggu sampai container "siap" (apa pun artinya untuk aplikasi khusus Anda) - hanya sampai container itu berjalan. Ada alasan bagus untuk ini.

Masalah menunggu database (misalnya) siap sebenarnya hanyalah bagian dari masalah sistem terdistribusi yang jauh lebih besar. Dalam produksi, database Anda dapat menjadi tidak tersedia atau memindahkan host kapan saja. Aplikasi Anda harus tahan terhadap jenis kegagalan ini.

Untuk menangani ini, aplikasi Anda harus mencoba membangun kembali koneksi ke database setelah gagal. Jika aplikasi mencoba kembali koneksi, pada akhirnya harus dapat terhubung ke database.

Solusi terbaik adalah melakukan pemeriksaan ini pada kode aplikasi Anda, baik saat startup maupun setiap kali koneksi terputus karena alasan apa pun .

Jadi ada celah yang pasti di sini dalam konteks orkestrasi wadah, tetapi kedua sikap ini tampaknya valid:

  1. Luwak dapat mendukung opsi untuk mencoba lagi pada koneksi pertama (mungkin default ke false dengan beberapa dokumentasi peringatan), atau
  2. Luwak dapat menempatkan tanggung jawab pada pengembang untuk menulis kode untuk mencoba lagi jika koneksi pertama gagal.

Tentu, ada celah, tetapi Anda bertanggung jawab untuk memutuskan apakah akan mencoba lagi jika koneksi awal gagal. Semua luwak memberitahu Anda bahwa itu gagal. Jika Anda membuat keputusan yang meragukan untuk menggunakan komposisi buruh pelabuhan dalam produksi (atau dalam konteks apa pun dalam hal ini), terserah Anda untuk menangani percobaan ulang kegagalan koneksi awal.

Sikap 2, maka.

Bagi siapa pun yang menginginkan koneksi ulang otomatis ketika koneksi pertama gagal, ini adalah cara saya menanganinya:

function createConnection (dbURL, options) {
    var db = mongoose.createConnection(dbURL, options);

    db.on('error', function (err) {
        // If first connect fails because mongod is down, try again later.
        // This is only needed for first connect, not for runtime reconnects.
        // See: https://github.com/Automattic/mongoose/issues/5169
        if (err.message && err.message.match(/failed to connect to server .* on first connect/)) {
            console.log(new Date(), String(err));

            // Wait for a bit, then try to connect again
            setTimeout(function () {
                console.log("Retrying first connect...");
                db.openUri(dbURL).catch(() => {});
                // Why the empty catch?
                // Well, errors thrown by db.open() will also be passed to .on('error'),
                // so we can handle them there, no need to log anything in the catch here.
                // But we still need this empty catch to avoid unhandled rejections.
            }, 20 * 1000);
        } else {
            // Some other error occurred.  Log it.
            console.error(new Date(), String(err));
        }
    });

    db.once('open', function () {
        console.log("Connection to db established.");
    });

    return db;
}

// Use it like
var db = createConnection('mongodb://...', options);
var User = db.model('User', userSchema);

Untuk luwak < 4.11 gunakan db.open() sebagai ganti db.openUri()
Untuk luwak 4.11.7 teknik ini tidak bekerja.
Untuk luwak 4.13.4 ini berfungsi lagi!


Sunting 2019/09/02: Ada juga solusi yang lebih pendek menggunakan promiseRetry sini .

Hai @ vkarpov15 ketika ini terjadi juga catat Penolakan yang Tidak Tertangani dari perpustakaan mongodb-core.

MongoError: failed to connect to server [localhost:27017] on first connect [MongoError: connect ECONNREFUSED 127.0.0.1:27017]
    at Pool.<anonymous> (/Users/development/okkralabs/sem-server/services/sem-access/node_modules/mongodb-core/lib/topologies/server.js:336:35)
    at emitOne (events.js:116:13)
    at Pool.emit (events.js:211:7)
    at Connection.<anonymous> (/Users/development/okkralabs/sem-server/services/sem-access/node_modules/mongodb-core/lib/connection/pool.js:280:12)
    at Object.onceWrapper (events.js:317:30)
    at emitTwo (events.js:126:13)
    at Connection.emit (events.js:214:7)
    at Socket.<anonymous> (/Users/development/okkralabs/sem-server/services/sem-access/node_modules/mongodb-core/lib/connection/connection.js:187:49)
    at Object.onceWrapper (events.js:315:30)
    at emitOne (events.js:116:13)
    at Socket.emit (events.js:211:7)
    at emitErrorNT (internal/streams/destroy.js:64:8)
    at _combinedTickCallback (internal/process/next_tick.js:138:11)
    at process._tickCallback (internal/process/next_tick.js:180:9)

Ini mudah direproduksi, coba sambungkan dengan server MongoDb yang tidak tersedia.

(node:2545) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): MongoError: failed to connect to server [localhost:27017] on first connect [MongoError: connect ECONNREFUSED 127.0.0.1:27017]
(node:2545) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

Beberapa cara untuk menanganinya?

@jorgearanda versi luwak apa yang Anda gunakan dan dapatkah Anda memberikan beberapa contoh kode?

@vkarpov15 Saya pikir itu pesan untuk @jorgecuesta ?

Ups, kesalahan saya. Pelengkapan otomatis github yang konyol, ya, itu untuk @jorgecuesta

Saya melihat hal yang sama persis dengan @jorgecuesta , saya menggunakan 4.11.5 dan tetapi melihat hal yang sama dengan 5.0.0-rc2. Saya menggunakan createConnection karena beberapa model menggunakan database yang berbeda pada instance mongo yang sama. Itu terjadi ketika memulai server saat mongo sedang down:

2018-01-07 13:05:23-05:00: [INFO] database - reusing existing connectioun for mongodb://localhost/eiss
2018-01-07 13:05:23-05:00: [INFO] database - initializing database connection to: mongodb://localhost/eiss
2018-01-07 13:05:23-05:00: [INFO] database - reusing existing connectioun for mongodb://localhost/eiss
2018-01-07 13:05:23-05:00: [ERROR] database - Mongoose connection error: MongoNetworkError: failed to connect to server [localhost:27017] on first connect [MongoNetworkError: connect ECONNREFUSED 127.0.0.1:27017]
Unhandled rejection MongoNetworkError: failed to connect to server [localhost:27017] on first connect [MongoNetworkError: connect ECONNREFUSED 127.0.0.1:27017]
    at Pool.<anonymous> (/Users/bill/eiss4/js/node_modules/mongoose/node_modules/mongodb-core/lib/topologies/server.js:503:11)
    at emitOne (events.js:116:13)
    at Pool.emit (events.js:211:7)
    at Connection.<anonymous> (/Users/bill/eiss4/js/node_modules/mongoose/node_modules/mongodb-core/lib/connection/pool.js:326:12)
    at Object.onceWrapper (events.js:317:30)
    at emitTwo (events.js:126:13)
    at Connection.emit (events.js:214:7)
    at Socket.<anonymous> (/Users/bill/eiss4/js/node_modules/mongoose/node_modules/mongodb-core/lib/connection/connection.js:245:50)
    at Object.onceWrapper (events.js:315:30)
    at emitOne (events.js:116:13)
    at Socket.emit (events.js:211:7)
    at emitErrorNT (internal/streams/destroy.js:64:8)
    at _combinedTickCallback (internal/process/next_tick.js:138:11)
    at process._tickCallback (internal/process/next_tick.js:180:9)

Model memanggil fungsi koneksi dengan nama database yang mereka gunakan (di bawah). Selama mongo berjalan ketika server mulai, membawa database ke atas dan ke bawah terhubung kembali dengan baik (mencatat kesalahan). Saya baru menyadari membaca masalah ini bahwa driver menangani koneksi awal secara berbeda, yang agak mengganggu. Saya akan mencoba solusi @joeytwiddle , tetapi saya menduga pengecualian yang tidak tertangani ini masih akan terjadi?

const allConnections = {};

module.exports = function(dbName) {
  const url = 'http://localhost/' + dbName;
  let conn;
  log.info('initializing database connection to: ' + url);

  conn = allConnections[url];
  if (!conn) {
    log.info('creating new connection for ' + url);
    conn = mongoose.createConnection(url, {
      useMongoClient: true,
      autoReconnect: true,
      autoIndex: false,
      reconnectTries: Number.MAX_SAFE_INTEGER
    });    
    // Log database connection events
    conn.on('connected', () => log.info('Mongoose connection open to ' + url));
    conn.on('error', (err) =>  log.error('Mongoose connection error: ' + err));
    conn.on('disconnected', () => log.error('Mongoose connection disconnected'));  
    allConnections[url] = conn;
  }
  else {
    log.info('reusing existing connection for ' + url);
  }
  return conn;
}

@raythree dalam kasus di atas Anda harus baik-baik saja karena Anda memiliki .on('error') . Jika Anda ingin mencoba kembali koneksi awal jika gagal, saya sarankan Anda hanya menggunakan async/menunggu untuk itu

let conn;
for (let i = 0; i < numRetries; ++i) {
  try {
    conn = await mongoose.createConnection(uri);
    break;
  } catch (error) {}
}

@vkarpov15 Maaf atas keterlambatan menjawab Anda, kami menggunakan 4.11.14 dan 4.13.4

@jorgecuesta melakukan mongoose.connect(uri).catch(err => {})

@vkarpov15 connect() mengembalikan contoh koneksi kan?

const connection = mongoose.connect(uri || undefined, {useMongoClient: true});
connection.once('error', (e) => {
  console.error(e, 'mongoose connection error.');
});
connection.once('connected', () => {
  console.log('mongoose connected');
});

Di 5.0.0 kami mengubahnya sehingga mongoose.connect() mengembalikan janji secara konsisten. Di 4.x ia mengembalikan instance koneksi tetapi dengan .then() dan .catch() sehingga Anda dapat menggunakannya dengan await

Hai @joeytwiddle.

Saya mengalami masalah yang sama pada penyebaran ke Heroku.
MongoNetworkError: failed to connect to server [localhost:27017] on first connect [MongoNetworkError: connect ECONNREFUSED 127.0.0.1:27017]

Pada komentar Anda pada 12 Juli 2017 Anda memberikan solusi/solusi. Saya baru mengenal Mongoose/Node.js. Bisakah Anda memberi tahu saya file apa yang harus digunakan oleh fungsi createConnection Anda?

Saya menjalankan luwak: ^5.0.10, node: v9.4.0
Bersulang

@juancarlucci Anda dapat meletakkannya di file apa pun yang Anda suka. Sebut saja untuk mendapatkan instance luwak dan gunakan itu untuk membuat model Anda.

Saya telah memperbarui komentar sebelumnya untuk menunjukkan contoh penggunaan.

@joeytwiddle Terima kasih atas contoh penggunaan! Bersulang.

Ketika saya mencoba terhubung ke mongo itu menimbulkan kesalahan:

connection error: { MongoNetworkError: failed to connect to server [localhost:27017] on first connect [MongoNetworkError: connection 0 to localhost:27017 timed out]
    at Pool.<anonymous> (/home/wasd_xyz/Desktop/test/node_modules/mongodb-core/lib/topologies/server.js:505:11)
    at emitOne (events.js:116:13)
    at Pool.emit (events.js:211:7)
    at Connection.<anonymous> (/home/wasd_xyz/Desktop/test/node_modules/mongodb-core/lib/connection/pool.js:329:12)
    at Object.onceWrapper (events.js:317:30)
    at emitTwo (events.js:126:13)
    at Connection.emit (events.js:214:7)
    at Socket.<anonymous> (/home/wasd_xyz/Desktop/test/node_modules/mongodb-core/lib/connection/connection.js:256:10)
    at Object.onceWrapper (events.js:313:30)
    at emitNone (events.js:106:13)
    at Socket.emit (events.js:208:7)
    at Socket._onTimeout (net.js:420:8)
    at ontimeout (timers.js:482:11)
    at tryOnTimeout (timers.js:317:5)
    at Timer.listOnTimeout (timers.js:277:5)
  name: 'MongoNetworkError',
  message: 'failed to connect to server [localhost:27017] on first connect [MongoNetworkError: connection 0 to localhost:27017 timed out]' }
(node:5453) UnhandledPromiseRejectionWarning: MongoNetworkError: failed to connect to server [localhost:27017] on first connect [MongoNetworkError: connection 0 to localhost:27017 timed out]
    at Pool.<anonymous> (/home/wasd_xyz/Desktop/test/node_modules/mongodb-core/lib/topologies/server.js:505:11)
    at emitOne (events.js:116:13)
    at Pool.emit (events.js:211:7)
    at Connection.<anonymous> (/home/wasd_xyz/Desktop/test/node_modules/mongodb-core/lib/connection/pool.js:329:12)
    at Object.onceWrapper (events.js:317:30)
    at emitTwo (events.js:126:13)
    at Connection.emit (events.js:214:7)
    at Socket.<anonymous> (/home/wasd_xyz/Desktop/test/node_modules/mongodb-core/lib/connection/connection.js:256:10)
    at Object.onceWrapper (events.js:313:30)
    at emitNone (events.js:106:13)
    at Socket.emit (events.js:208:7)
    at Socket._onTimeout (net.js:420:8)
    at ontimeout (timers.js:482:11)
    at tryOnTimeout (timers.js:317:5)
    at Timer.listOnTimeout (timers.js:277:5)
(node:5453) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:5453) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.


status mongodb layanan sudo

● mongodb.service - MongoDB Database
   Loaded: loaded (/etc/systemd/system/mongodb.service; enabled; vendor preset: 
   Active: active (running) since Sat 2018-06-23 17:13:28 IST; 13min ago
     Docs: https://docs.mongodb.org/manual
 Main PID: 4224 (mongod)
    Tasks: 24 (limit: 4915)
   CGroup: /system.slice/mongodb.service
           └─4224 /usr/bin/mongod --quiet --config /etc/mongod.conf

Jun 23 17:13:28 Inspiron5370 systemd[1]: Started MongoDB Database.


@pranshuchittora dapatkah Anda menunjukkan file konfigurasi MongoDB Anda? Pastikan portnya 27017. Juga, coba gunakan 127.0.0.1 alih-alih localhost

Coba sambungkan dengan ip alih-alih localhost yang akan memperbaiki masalah Anda.

 let local = "mongodb://127.0.0.1:27017/XXX";
      mongoose.connect(
        local,
        { useNewUrlParser: true }
      );

Jika upaya pertama untuk terhubung gagal, itu selalu menimbulkan kesalahan.
Anda dapat melewati ini menggunakan di bawah ini (mis. Ketika ingin memastikan bahwa DB berjalan sebelum Anda memulai aplikasi/skrip):

[email protected]
@types/ [email protected]
@types/ [email protected]

async function waitForMongoDBStart(uri: string, timeoutMs: number) {

    return new Promise( async (resolve, reject) => {

        let endTime = Date.now() + timeoutMs;


        while (true) {

            let connectionError: Error;

            function errorHandler(err: Error) {
                connectionError = err;
            }
            mongoose.connection.once("error", errorHandler);

            await mongoose.connect(uri, {
                connectTimeoutMS: 5000, // This timeout applies only after connected & connection lost
                useNewUrlParser: true,
                useFindAndModify: false
            });

            // Time for error event propagation
            await wait(0);

            if ( ! connectionError) {
                mongoose.connection.removeListener("error", errorHandler);
                return resolve(); // All OK, connected
            }

            if (connectionError.name !== "MongoNetworkError") {
                return reject(`Unable to connect mongoDB. Details: ${connectionError}`);
            }

            if (Date.now() > endTime) {
                return reject(`Unable to connect mongoBD in ${timeoutMs} ms. Details: ${connectionError}`);
            }

        }

    });
}

@vkarpov15 Ini adalah perilaku yang sangat tidak jelas. Dari https://mongoosejs.com/docs/connections.html :

connectTimeoutMS - How long the MongoDB driver will wait 
before failing its initial connection attempt. 
Once Mongoose has successfully connected, connectTimeoutMS is no longer relevant.

Dokumentasi mengatakan bahwa itu harus bekerja dengan koneksi awal, tetapi tidak. Dengan failed to connect to server kesalahan itu langsung gagal.

Jika perilakunya konsisten di seluruh driver MongoDB, alangkah baiknya memiliki beberapa opsi seperti reconnectOnInitialFail yang akan menjadi false secara default

Perilaku saat ini berlawanan dengan yang dijelaskan oleh vkarpov15 -
connectImeoutMS hanya penting setelah koneksi pertama (pada koneksi pertama itu
diharapkan DB dimulai dan menerima koneksi, jika tidak segera
kesalahan dilemparkan)

sob., 22 gru 2018 o 13:03 Dmitry Kirilyuk [email protected]
napisał(a):

Jika itu perilaku yang konsisten di seluruh driver MongoDB, alangkah baiknya untuk
memiliki beberapa opsi seperti reconnectOnInitialFail yang akan salah dengan
bawaan


Anda menerima ini karena Anda berkomentar.
Balas email ini secara langsung, lihat di GitHub
https://github.com/Automattic/mongoose/issues/5169#issuecomment-449565468 ,
atau matikan utasnya
https://github.com/notifications/unsubscribe-auth/ABY-TjgeI2UqVca050y5YY3zi6w7nMkfks5u7h-vgaJpZM4M-1ur
.

--
Wojciech Fiderek

Seluler: +48 516 661 428

Jika saya ingat dengan benar, connectTimeoutMS penting pada koneksi awal tergantung pada kondisi jaringan dan os. Kapan connectTimeoutMS penting setelah koneksi awal?

Dalam kasus saya, kesalahan langsung terjadi ketika saya tidak dapat terhubung pada percobaan pertama ke instance mongod localhost di Windows 10 dan Alpine Linux (versi tidak diketahui). Instance Mongod belum dimulai.
Contoh lain selain localhost? Siapa pun?

@fider @Jokero Saya menggali lebih jauh, dan saya benar, connectTimeoutMS hanya penting sampai Anda membuat koneksi awal, socketTimeoutMS mengambil alih sesudahnya. Berikut kode yang relevan di driver MongoDB:

connectTimeoutMS tidak selalu berguna karena Anda biasanya akan mendapatkan kesalahan DNS atau kesalahan koneksi ditolak. Tetapi jika Anda, katakanlah, membuka server TCP yang mendengarkan pada port tetapi tidak benar-benar melakukan apa pun:

const net = require('net');

const server = net.createServer();

server.listen(27055);

Anda akan melihat bahwa connectTimeoutMS dimulai:

const assert = require('assert');
const mongoose = require('mongoose');
mongoose.set('debug', true);

const { Schema } = mongoose;

run().then(() => console.log('done')).catch(error => console.error(error.stack));

async function run() {
  await mongoose.connect('mongodb://localhost:27055', {
    useNewUrlParser: true,
    connectTimeoutMS: 1000,
    socketTimeoutMS: 25000
  });
} 
$ time node gh-5169.js 
MongoNetworkError: connection 0 to localhost:27055 timed out
    at Socket.<anonymous> (/mongoose/node_modules/mongodb-core/lib/connection/connection.js:259:7)
    at Object.onceWrapper (events.js:313:30)
    at emitNone (events.js:106:13)
    at Socket.emit (events.js:208:7)
    at Socket._onTimeout (net.js:407:8)
    at ontimeout (timers.js:475:11)
    at tryOnTimeout (timers.js:310:5)
    at Timer.listOnTimeout (timers.js:270:5)

real    0m2.293s
user    0m0.271s
sys 0m0.043s
$ 

terkadang karena batasan jaringan, url MongoDB diblokir, coba ubah sumber jaringan/internet Anda.

https://stackoverflow.com/questions/47958683/cannot-connect-to-mongodb-atlas-through-mongo-shell?answertab=active#tab -top

Saat membuat koneksi awal, (setidaknya) tiga hal dapat terjadi:

  1. Ada mongodb dan koneksi berhasil, yay!

  2. Server merespon "Koneksi ditolak" yang berarti tidak ada proses yang mendengarkan pada port ini, atau ada firewall yang _secara aktif menolak_ koneksi. (Ini biasanya terjadi segera, dan saya pikir inilah yang dialami fider.)

  3. Server tidak merespon sama sekali, misalnya firewall _secara pasif menjatuhkan_ paket atau tidak ada server pada alamat IP tersebut. (Dalam kasus ini, connectTimeoutMS vkarpov akhirnya terpicu.)

Jadi timeout tidak selalu digunakan. Ini hanya digunakan jika tidak ada keberhasilan atau kegagalan yang jelas dalam waktu tertentu.

Ini biasa terjadi dalam jaringan, dan juga ketika berbicara dengan orang yang tidak kooperatif. Permintaan Anda bisa mendapatkan dua jenis penolakan: "TIDAK!" dan .....

Terima kasih atas penjelasan yang solid @joeytwiddle :+1:

Bagaimana seharusnya seseorang menangani perilaku ini dengan koneksi set replika menggunakan mongodb+srv ? Ketika set replika saya dalam skenario restart bergulir (pembaruan basis data) saya mulai mendapatkan kesalahan seperti connect ECONNREFUSED 34.238.xxx.xxx:27017 .

@esetnik apakah Anda menggunakan useUnifiedTopology: true dan Mongoose 5.7.5? Kami mengidentifikasi masalah #8209 yang mungkin terkait.

@vkarpov15 ya saya! Terima kasih atas tipnya. Saya akan menjalankan beberapa tes setelah menonaktifkan topologi terpadu dan melaporkan kembali temuan saya.

Hai. Saya memiliki masalah yang sama persis di proyek saya. apakah kamu sudah menemukan solusi untuk itu?!

@fdmxfarhan silakan buka terbitan terpisah dan ikuti templat terbitan.

Apakah halaman ini membantu?
0 / 5 - 0 peringkat