Mongoose: Es werden keine Wiederholungsversuche nach "Verbindung beim ersten Verbinden fehlgeschlagen" durchgeführt.

Erstellt am 17. Apr. 2017  ·  40Kommentare  ·  Quelle: Automattic/mongoose

Standardmäßig löst Mungo einen Fehler aus, wenn die erste Verbindung fehlschlägt, was den Knoten zum Absturz bringt.

Um diesen Fehler zu reproduzieren, benötigen Sie den folgenden Code in Ihrer App, um den Fehler abzufangen und den Absturz zu verhindern:

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

Jetzt können wir diesen Fehler wie folgt reproduzieren:

  1. Fahren Sie Ihre MongoDB herunter
  2. Starten Sie Ihre Knoten-App, die Mungo verwendet
  3. Ihre App protokolliert: [MongoError: failed to connect to server [localhost:27017] on first connect [MongoError: connect ECONNREFUSED 127.0.0.1:27017]]
  4. Starten Sie Ihre MongoDB erneut
  5. Beachten Sie, dass Mungo jetzt keine Verbindung zur funktionierenden MongoDB herstellt. Die einzige Möglichkeit, die Verbindung wiederherzustellen, besteht darin, Ihre App neu zu starten oder eine manuelle Problemumgehung zu verwenden .

Erwartetes Verhalten: Da autoreconnect standardmäßig auf true gesetzt ist, würde ich erwarten, dass Mongoose bald eine Verbindung herstellt, nachdem die MongoDB wieder zugänglich ist.

Hinweis: Wenn die erste Verbindung erfolgreich ist, die Verbindung zu MongoDB jedoch während der Laufzeit verloren geht, funktioniert die automatische Wiederverbindung wie erwartet einwandfrei. Das Problem ist die Inkonsistenz, wenn MongoDB beim Start der App nicht verfügbar ist.

(Wenn dies das gewünschte Verhalten ist und Entwicklern empfohlen wird, mit dieser Situation umzugehen, indem sie den Fehler nicht abfangen und den Knoten abstürzen lassen, kann ich das akzeptieren, aber es lohnt sich, es klarzustellen.)

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

docs

Hilfreichster Kommentar

Für alle, die eine automatische Wiederverbindung wünschen, wenn die erste Verbindung fehlschlägt, gehe ich folgendermaßen vor:

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

Für Mungos < 4.11 verwenden Sie db.open() anstelle von db.openUri()
Bei Mungo 4.11.7 funktioniert diese Technik nicht.
Für Mungo 4.13.4 funktioniert es wieder!


Edit 02.09.2019: Es gibt auch eine kürzere Lösung mit promiseRetry hier .

Alle 40 Kommentare

kann bestätigen.
Knoten 6, 7, Mungo (mindestens 6 Monate), Mungo 3.2 - 3.4
kommt zusammen mit diesem #4890

Ich vermute, das ist ein mongodb-core Problem. Es sollte versuchen, sich erneut zu verbinden, auch wenn der erste Versuch fehlschlägt, da ich mir nicht sicher bin, warum sich das von nachfolgenden Versuchen unterscheidet.

Können Sie dieses Problem auch dort melden?

Hier ist ein vollständiges Repro-Skript:

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

Danke für die Reproduktion. Ich habe mir mongodb-core angesehen. Es ist das beabsichtigte Verhalten des Fahrers :

Der Treiber schlägt beim ersten Verbinden fehl, wenn er keine Verbindung zum Host herstellen kann. Dies ist beabsichtigt, um einen schnellen Ausfall auf nicht erreichbaren Hosts zu gewährleisten. Das Wiederverbindungsverhalten tritt erst ein, wenn der Treiber die anfängliche Verbindung durchgeführt hat.

Es liegt an der Anwendung, zu entscheiden, was zu tun ist. Dies ist beabsichtigt, um sicherzustellen, dass der Treiber schnell ausfällt und nicht so sitzt, dass Sie denken, dass er tatsächlich funktioniert.

Ich vermute also, dass wir vom Fahrer kein anderes Verhalten bekommen werden.

Ich denke eigentlich, dass dieses Verhalten für einen Low-Level-Treiber angemessen ist. Es hilft Entwicklern, die versehentlich versuchen, sich mit dem falschen Host oder dem falschen Port zu verbinden.

Aber wenn wir in Mungo etwas Entwicklerfreundlicheres machen möchten, könnten wir Folgendes in Betracht ziehen:

  • Wenn die Optionen für die automatische Wiederverbindung aktiviert sind, versuchen Sie so lange, die Verbindung wiederherzustellen, bis der Mongo-Server kontaktiert werden kann (indem Sie so etwas wie die oben verlinkte Problemumgehung einbauen).
  • Protokollieren Sie, wenn Mungo dies tut, damit im Falle einer Verbindung, die nie hergestellt wird, der Entwickler zumindest weiß, wo das Problem liegt.
    (Die Protokollierung könnte verschoben werden, zB 30 Sekunden. Eigentlich sollten wir anstelle einer direkten Protokollierung ein Hinweisereignis error ausgeben, aber trotzdem versuchen, die Verbindung automatisch wieder herzustellen.)

Wenn ich mich richtig erinnere, wurden bereits von der App in die Warteschlange gestellte Abfragen wie gewünscht ausgeführt, als ich den Workaround verwendet und nach einigen fehlgeschlagenen Versuchen schließlich eine Verbindung hergestellt habe. (Aber das ist einen erneuten Test wert.)

Ich denke, das ist eigentlich eine anständige Idee, ich werde das als Feature-Request bezeichnen

Nein, ein schnelles Versagen bei der ersten Verbindung ist ein ziemlich konsistentes Verhalten bei allen MongoDB-Treibern, und es bringt nicht viel, wenn Mungo dies unterstützt.

Dieser aktuelle Beitrag vom Strongloop Loopback mongodb-Connector könnte relevant sein. Ihr lazyConnect Flag verzögert die erste Verbindung, bis der Endpunkt erreicht ist. Wenn in diesem Fall die erste Verbindung fehlschlägt, werden die Standardeinstellungen für den Verbindungsverlust wirksam (es wird erneut versucht).

Mein Interesse gilt der Container-Orchestrierung, bei der die "Container-Startreihenfolge" oft festgelegt und erwartet werden kann, die "Reihenfolge der Dienstverfügbarkeit" jedoch nicht. Ein Orchestrierungstool bestätigt möglicherweise, dass der Mongo-Container "up" ist, obwohl der Mongo-Dienst noch nicht verfügbar ist.

Wenn mein Mongo-Container also 1 Sekunde braucht, um zu starten, aber 5 Sekunden, bis der Dienst verfügbar ist, und mein App-Container 1 Sekunde braucht, um zu starten und 1 Sekunde, bis der Dienst verfügbar ist, wird der App-Dienst den Mongo-Dienst überholen, was zu einem ersten Verbindungsfehler führt wie ursprünglich beschrieben .

Die Docker Compose-Dokumentation sagt Folgendes:

Compose wartet nicht, bis ein Container „bereit“ ist (was auch immer das für Ihre spezielle Anwendung bedeutet), sondern nur, bis er ausgeführt wird. Das hat einen guten Grund.

Das Problem des Wartens (zum Beispiel) auf die Bereitstellung einer Datenbank ist eigentlich nur eine Teilmenge eines viel größeren Problems verteilter Systeme. In der Produktion kann Ihre Datenbank jederzeit nicht verfügbar sein oder Hosts verschieben. Ihre Anwendung muss gegen diese Art von Fehlern widerstandsfähig sein.

Um dies zu handhaben, sollte Ihre Anwendung nach einem Fehler versuchen, eine Verbindung zur Datenbank wiederherzustellen. Wenn die Anwendung die Verbindung erneut versucht, sollte sie schließlich in der Lage sein, eine Verbindung zur Datenbank herzustellen.

Die beste Lösung besteht darin, diese Prüfung in Ihrem Anwendungscode durchzuführen, sowohl beim Start als auch immer dann, wenn eine Verbindung aus irgendeinem Grund unterbrochen wird .

Im Kontext der Container-Orchestrierung gibt es hier also eine eindeutige Lücke, aber beide Standpunkte scheinen gültig zu sein:

  1. Mongoose könnte eine Option zum erneuten Versuch bei der ersten Verbindung unterstützen (möglicherweise standardmäßig auf false mit einer warnenden Dokumentation) oder
  2. Mongoose könnte dem Entwickler die Verantwortung übertragen, Code zu schreiben, um es erneut zu versuchen, wenn die erste Verbindung fehlschlägt.

Sicher, es gibt eine Lücke, aber dann liegt es bei Ihnen, zu entscheiden, ob Sie es erneut versuchen, wenn die anfängliche Verbindung fehlschlägt. Alles, was Mungo Ihnen sagt, ist, dass es fehlgeschlagen ist. Wenn Sie die fragwürdige Entscheidung treffen, Docker Compose in der Produktion (oder in jedem anderen Kontext) zu verwenden, liegt es an Ihnen, die anfänglichen Verbindungsfehler erneut zu versuchen.

Haltung 2 ist es also.

Für alle, die eine automatische Wiederverbindung wünschen, wenn die erste Verbindung fehlschlägt, gehe ich folgendermaßen vor:

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

Für Mungos < 4.11 verwenden Sie db.open() anstelle von db.openUri()
Bei Mungo 4.11.7 funktioniert diese Technik nicht.
Für Mungo 4.13.4 funktioniert es wieder!


Edit 02.09.2019: Es gibt auch eine kürzere Lösung mit promiseRetry hier .

Hallo @vkarpov15, wenn dies auftritt, protokolliere auch eine nicht behandelte Ablehnung aus der mongodb-core-Bibliothek.

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)

Dies ist leicht zu reproduzieren, versuchen Sie, eine Verbindung zu einem nicht verfügbaren MongoDb-Server herzustellen.

(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.

Eine Möglichkeit, damit umzugehen?

@jorgearanda welche Version von Mungo verwenden Sie und können Sie einige Codebeispiele bereitstellen?

@vkarpov15 Ich denke, das ist eine Nachricht für @jorgecuesta ?

Ups, mein Fehler. Dumme Github-Autovervollständigung, ja, das war für @jorgecuesta

Ich sehe genau dasselbe wie @jorgecuesta , ich habe 4.11.5 verwendet und sehe dasselbe mit 5.0.0-rc2. Ich verwende createConnection, da einige der Modelle verschiedene Datenbanken auf derselben Mongo-Instanz verwenden. Es passiert, wenn der Server gestartet wird, während mongo ausgefallen ist:

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)

Die Modelle rufen eine Verbindungsfunktion mit dem Namen der verwendeten Datenbank auf (unten). Solange mongo läuft, wenn der Server startet, ist das Hoch- und Herunterfahren der Datenbank problemlos wieder verbunden (Protokollierung der Fehler). Mir ist gerade beim Lesen dieses Problems aufgefallen, dass der Treiber die anfängliche Verbindung anders handhabt, was irgendwie nervig ist. Ich werde die Problemumgehung von @joeytwiddle ausprobieren, aber ich vermute, dass diese unbehandelte Ausnahme weiterhin auftreten wird?

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 im obigen Fall sollte es Ihnen gut gehen, weil Sie .on('error') . Wenn Sie die anfängliche Verbindung erneut versuchen möchten, wenn sie fehlschlägt, würde ich Ihnen jedoch empfehlen, dafür einfach async/await zu verwenden

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

@vkarpov15 Entschuldigung für die Verzögerung bei der Beantwortung, wir verwenden 4.11.14 und 4.13.4

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

@vkarpov15 connect() gibt die Verbindungsinstanz zurück, oder?

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

In 5.0.0 haben wir es so geändert, dass mongoose.connect() konsistent ein Versprechen zurückgibt. In 4.x gibt es eine Verbindungsinstanz zurück, jedoch mit .then() und .catch() sodass Sie sie mit await

Hallo @joeytwiddle.

Ich habe das gleiche Problem bei der Bereitstellung in Heroku.
MongoNetworkError: failed to connect to server [localhost:27017] on first connect [MongoNetworkError: connect ECONNREFUSED 127.0.0.1:27017]

In Ihrem Kommentar vom 12. Juli 2017 haben Sie einen Workaround/eine Lösung angegeben. Ich bin ganz neu bei Mongoose/Node. Können Sie mir sagen, in welche Datei Ihre createConnection-Funktion gehen soll?

Ich verwende Mungo: ^5.0.10, Knoten: v9.4.0
Danke schön

@juancarlucci Sie können es in eine beliebige Datei

Ich habe den früheren Kommentar aktualisiert, um ein Anwendungsbeispiel zu zeigen.

@joeytwiddle Danke für das Anwendungsbeispiel! Danke schön.

Wenn ich versuche, eine Verbindung zu Mongo herzustellen, wird ein Fehler ausgegeben:

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.


sudo service mongodb status

● 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 können Sie Ihre MongoDB-Konfigurationsdatei

Versuchen Sie, eine Verbindung mit IP anstelle von localhost herzustellen, um Ihr Problem zu beheben.

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

Wenn der erste Verbindungsversuch fehlschlägt, wird immer ein Fehler ausgegeben.
Sie können dies unten umgehen (z. B. wenn Sie sicherstellen möchten, dass die DB ausgeführt wird, bevor Sie die App/das Skript starten):

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

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 Dies ist ein sehr nicht offensichtliches Verhalten. Von 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.

Die Dokumentation sagt, dass es mit der ersten Verbindung funktionieren sollte, aber das tut es nicht. Mit failed to connect to server Fehler schlägt es sofort fehl.

Wenn das Verhalten der MongoDB-Treiber konsistent ist, wäre es schön, eine Option wie reconnectOnInitialFail die standardmäßig false ist

Das aktuelle Verhalten ist dem von vkarpov15 beschriebenen entgegengesetzt -
connectImeoutMS ist nur nach der ersten Verbindung wichtig (bei der ersten Verbindung ist es
wird erwartet, dass DB gestartet wird und die Verbindung akzeptiert, ansonsten sofort
Fehler wird geworfen)

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

Wenn das Verhalten der MongoDB-Treiber konsistent ist, wäre es schön, wenn
haben eine Option wie reconnectOnInitialFail, die falsch sein wird
Ursprünglich


Sie erhalten dies, weil Sie einen Kommentar abgegeben haben.
Antworten Sie direkt auf diese E-Mail und zeigen Sie sie auf GitHub an
https://github.com/Automattic/mongoose/issues/5169#issuecomment-449565468 ,
oder den Thread stumm schalten
https://github.com/notifications/unsubscribe-auth/ABY-TjgeI2UqVca050y5YY3zi6w7nMkfks5u7h-vgaJpZM4M-1ur
.

--
Wojciech Fiderek

Handy: +48 516 661 428

Wenn ich mich richtig erinnere, ist connectTimeoutMS bei der ersten Verbindung abhängig von den Netzwerkbedingungen und dem Betriebssystem von Bedeutung. Wann ist connectTimeoutMS nach der ersten Verbindung von Bedeutung?

In meinem Fall wurde ein sofortiger Fehler ausgegeben, als ich beim ersten Versuch keine Verbindung zur localhost mongod-Instanz unter Windows 10 und Alpine Linux (Version unbekannt) herstellen konnte. Mongod-Instanz ist noch nicht gestartet.
Andere Beispiele als localhost? Jeder?

@fider @Jokero Ich habe weiter gegraben, und ich habe Recht, connectTimeoutMS nur wichtig, bis Sie eine erste Verbindung hergestellt haben, socketTimeoutMS übernimmt danach. Hier ist der relevante Code im MongoDB-Treiber:

connectTimeoutMS ist nicht immer nützlich, da Sie normalerweise einen DNS-Fehler oder einen Fehler beim Zurückweisen der Verbindung erhalten. Aber wenn Sie beispielsweise einen TCP-Server öffnen, der an einem Port lauscht, aber eigentlich nichts tut:

const net = require('net');

const server = net.createServer();

server.listen(27055);

Sie werden sehen, dass connectTimeoutMS :

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
$ 

Manchmal werden die MongoDB-URLs aufgrund von Netzwerkbeschränkungen blockiert. Versuchen Sie, Ihre Netzwerk- / Internetquelle zu ändern.

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

Bei einer Erstverbindung können (mindestens) drei Dinge passieren:

  1. Es gibt eine Mongodb und die Verbindung ist erfolgreich, yay!

  2. Der Server antwortet mit "Verbindung abgelehnt", was bedeutet, dass kein Prozess auf diesem Port lauscht oder eine Firewall die Verbindung _aktiv zurückgewiesen_ hat. (Dies geschieht normalerweise sofort, und ich denke, das hat Fider erlebt.)

  3. Der Server antwortet überhaupt nicht, zB hat die Firewall die Pakete _passiv verworfen_ oder es gibt keinen Server an dieser IP-Adresse. (In diesem Fall wird schließlich connectTimeoutMS vkarpov ausgelöst.)

Das Timeout wird also nicht immer verwendet. Es wird nur verwendet, wenn es in der vorgegebenen Zeit keinen eindeutigen Erfolg oder Misserfolg gibt.

Dies ist beim Netzwerken üblich und auch beim Gespräch mit einer unkooperativen Person. Ihre Anfrage kann auf zwei Arten abgelehnt werden: "NEIN!" und .....

Danke für die solide Erklärung @joeytwiddle :+1:

Wie sollte man dieses Verhalten bei Replikatsatzverbindungen mit mongodb+srv handhaben? Wenn sich mein Replikatsatz in einem rollierenden Neustartszenario (Datenbankaktualisierung) befindet, erhalte ich Fehler wie connect ECONNREFUSED 34.238.xxx.xxx:27017 .

@esetnik verwendest du useUnifiedTopology: true und Mongoose 5.7.5? Wir haben ein Problem Nr. 8209 identifiziert, das möglicherweise damit zusammenhängt.

@vkarpov15 ja, das bin ich! Danke für den Tipp. Ich werde nach dem Deaktivieren der einheitlichen Topologie einige Tests durchführen und meine Ergebnisse zurückmelden.

Hi. Ich habe genau das gleiche Problem in meinem Projekt. hast du eine lösung dafür gefunden?!

@fdmxfarhan bitte öffnen Sie ein separates Issue und folgen Sie der Issue-Vorlage.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen