Wie konfiguriere ich den MongoDB Java-Treiber MongoOptions für die Verwendung in der Produktion?

100

Ich habe im Internet nach Best Practices für die Konfiguration von MongoOptions für den MongoDB-Java-Treiber gesucht und mir nur die API ausgedacht. Diese Suche begann, nachdem ich auf den Fehler "com.mongodb.DBPortPool $ SemaphoresOut: Keine Semaphore mehr, um eine Datenbankverbindung zu erhalten" gestoßen war, und durch Erhöhen der Verbindungen / des Multiplikators konnte ich dieses Problem lösen. Ich suche nach Links zu oder Ihren Best Practices bei der Konfiguration dieser Optionen für die Produktion.

Die Optionen für den 2.4-Treiber umfassen: http://api.mongodb.org/java/2.4/com/mongodb/MongoOptions.html

  • autoConnectRetry
  • VerbindungenPerHost
  • Verbindungs ​​Timeout
  • maxWaitTime
  • socketTimeout
  • threadsAllowedToBlockForConnectionMultiplier

Die neueren Treiber haben mehr Optionen und ich würde mich auch dafür interessieren.

Dan Polites
quelle

Antworten:

160

Auf 2.9 aktualisiert:

  • autoConnectRetry bedeutet einfach, dass der Treiber nach unerwarteten Verbindungsabbrüchen automatisch versucht, die Verbindung zu den Servern wiederherzustellen . In Produktionsumgebungen möchten Sie normalerweise, dass dieser Wert auf true gesetzt wird.

  • VerbindungenPerHost ist die Anzahl der physischen Verbindungen, die eine einzelne Mongo-Instanz (es ist Singleton, sodass Sie normalerweise eine pro Anwendung haben) zu einem Mongod / Mongos-Prozess herstellen kann. Zum Zeitpunkt des Schreibens stellt der Java-Treiber diese Anzahl von Verbindungen schließlich auch dann her, wenn der tatsächliche Abfragedurchsatz niedrig ist (in der Reihenfolge der Wörter wird die Statistik "conn" in mongostat angezeigt, bis diese Zahl pro App-Server erreicht wird).

    In den meisten Fällen muss dieser Wert nicht höher als 100 eingestellt werden, aber diese Einstellung ist eine dieser "Test it and see" -Dinge. Beachten Sie, dass Sie sicherstellen müssen, dass diese niedrig genug eingestellt ist, damit die Gesamtzahl der Verbindungen zu Ihrem Server nicht überschritten wird

    db.serverStatus().connections.available

    In der Produktion haben wir derzeit diese bei 40.

  • connectTimeout . Wie der Name schon sagt, wartet der Treiber in Millisekunden, bevor ein Verbindungsversuch abgebrochen wird. Stellen Sie das Zeitlimit auf etwas Langes (15 bis 30 Sekunden) ein, es sei denn, es besteht eine realistische, erwartete Wahrscheinlichkeit, dass dies ansonsten erfolgreichen Verbindungsversuchen im Wege steht. Wenn ein Verbindungsversuch länger als ein paar Sekunden dauert, kann Ihre Netzwerkinfrastruktur normalerweise keinen hohen Durchsatz erzielen.

  • maxWaitTime . Anzahl der ms, die ein Thread darauf wartet, dass eine Verbindung im Verbindungspool verfügbar wird, und eine Ausnahme auslöst, wenn dies nicht rechtzeitig geschieht. Standard beibehalten.

  • socketTimeout . Standardwert für Socket-Timeout. Auf 60 Sekunden (60000) einstellen.

  • threadsAllowedToBlockForConnectionMultiplier . Multiplikator für VerbindungenPerHost, der die Anzahl der Threads angibt, die warten dürfen, bis Verbindungen verfügbar sind, wenn der Pool derzeit erschöpft ist. Dies ist die Einstellung, die die Ausnahme "com.mongodb.DBPortPool $ SemaphoresOut: Aus Semaphoren, um eine Datenbankverbindung zu erhalten" verursacht. Diese Ausnahme wird ausgelöst, sobald diese Thread-Warteschlange den Wert threadsAllowedToBlockForConnectionMultiplier überschreitet. Wenn beispielsweise der connectionPerHost 10 und dieser Wert 5 beträgt, können bis zu 50 Threads blockieren, bevor die oben genannte Ausnahme ausgelöst wird.

    Wenn Sie große Spitzen im Durchsatz erwarten, die zu großen Warteschlangen führen können, erhöhen Sie diesen Wert vorübergehend. Wir haben es im Moment um 1500 aus genau diesem Grund. Wenn Ihre Abfragelast den Server konstant übertrifft, sollten Sie lediglich Ihre Hardware- / Skalierungssituation entsprechend verbessern.

  • readPreference . (AKTUALISIERT, 2.8+) Wird verwendet, um die Standardlesepräferenz zu bestimmen und ersetzt "SlaveOk". Richten Sie eine ReadPreference über eine der Klassenfactory-Methoden ein. Eine vollständige Beschreibung der häufigsten Einstellungen finden Sie am Ende dieses Beitrags

  • w . (AKTUALISIERT, 2.6+) Dieser Wert bestimmt die "Sicherheit" des Schreibvorgangs. Wenn dieser Wert -1 ist, meldet der Schreibvorgang keine Fehler, unabhängig von Netzwerk- oder Datenbankfehlern. WriteConcern.NONE ist hierfür das entsprechende vordefinierte WriteConcern. Wenn w 0 ist, schlagen Netzwerkfehler beim Schreiben fehl, Mongo-Fehler jedoch nicht. Dies wird normalerweise als "Fire and Forget" -Schreibvorgänge bezeichnet und sollte verwendet werden, wenn die Leistung wichtiger ist als Konsistenz und Haltbarkeit. Verwenden Sie für diesen Modus WriteConcern.NORMAL.

    Wenn Sie w auf 1 oder höher setzen, wird das Schreiben als sicher angesehen. Sichere Schreibvorgänge führen den Schreibvorgang durch und senden anschließend eine Anforderung an den Server, um sicherzustellen, dass der Schreibvorgang erfolgreich war, oder rufen einen Fehlerwert ab, wenn dies nicht der Fall ist (dh, nach dem Schreiben wird ein Befehl getLastError () gesendet). Beachten Sie, dass die Verbindung reserviert ist, bis dieser Befehl getLastError () abgeschlossen ist. Infolgedessen und aufgrund des zusätzlichen Befehls ist der Durchsatz erheblich niedriger als beim Schreiben mit w <= 0. Mit einem aw-Wert von genau 1 garantiert MongoDB, dass der Schreibvorgang für die Instanz, an die Sie den Schreibvorgang gesendet haben, erfolgreich war (oder nachweislich fehlgeschlagen ist).

    Im Fall von Replikatsätzen können Sie höhere Werte für w verwenden, um MongoDB anzuweisen, den Schreibvorgang vor der Rückkehr an mindestens "w" -Mitglieder des Replikatsatzes zu senden (oder genauer gesagt, warten Sie auf die Replikation Ihres Schreibvorgangs an "w" -Mitglieder ). Sie können w auch auf die Zeichenfolge "Mehrheit" setzen, die MongoDB anweist, den Schreibvorgang für die Mehrheit der Replikatsatzmitglieder (WriteConcern.MAJORITY) durchzuführen. Normalerweise sollten Sie dies auf 1 setzen, es sei denn, Sie benötigen eine unformatierte Leistung (-1 oder 0) oder replizierte Schreibvorgänge (> 1). Werte über 1 haben einen erheblichen Einfluss auf den Schreibdurchsatz.

  • fsync . Haltbarkeitsoption, die Mongo zwingt, nach jedem Schreibvorgang auf die Festplatte zu spülen, wenn diese aktiviert ist. Ich hatte noch nie Probleme mit der Haltbarkeit im Zusammenhang mit einem Schreibstau, daher haben wir dies bei false (Standardeinstellung) in der Produktion.

  • j * (NEU 2.7+) *. Boolean, dass MongoDB bei der Einstellung auf true gezwungen ist, auf ein erfolgreiches Festschreiben der Journalgruppe zu warten, bevor es zurückkehrt. Wenn Sie das Journaling aktiviert haben, können Sie dies für zusätzliche Haltbarkeit aktivieren. Unter http://www.mongodb.org/display/DOCS/Journaling erfahren Sie, mit welchem ​​Journaling Sie arbeiten (und warum Sie dieses Flag möglicherweise aktivieren möchten).

ReadPreference Mit der ReadPreference-Klasse können Sie konfigurieren, an welche Mongod-Instanzabfragen weitergeleitet wird, wenn Sie mit Replikatsätzen arbeiten. Folgende Optionen stehen zur Verfügung:

  • ReadPreference.primary () : Alle Lesevorgänge gehen nur an das primäre Repset-Mitglied. Verwenden Sie diese Option, wenn alle Abfragen konsistente (zuletzt geschriebene) Daten zurückgeben müssen. Dies ist die Standardeinstellung.

  • ReadPreference.primaryPreferred () : Alle Lesevorgänge werden nach Möglichkeit an das primäre Repset-Mitglied gesendet, können jedoch sekundäre Mitglieder abfragen, wenn der primäre Knoten nicht verfügbar ist. Wenn die Primärdaten nicht mehr verfügbar sind, werden die Lesevorgänge schließlich konsistent, jedoch nur, wenn die Primärdaten nicht verfügbar sind.

  • ReadPreference.secondary () : Alle Lesevorgänge werden an sekundäre Repset-Mitglieder gesendet, und das primäre Mitglied wird nur für Schreibvorgänge verwendet. Verwenden Sie dies nur, wenn Sie mit eventuell konsistenten Lesevorgängen leben können. Zusätzliche Repset-Mitglieder können verwendet werden, um die Leseleistung zu erhöhen, obwohl die Anzahl der (stimmberechtigten) Mitglieder, die ein Repset haben kann, begrenzt ist.

  • ReadPreference.secondaryPreferred () : Alle Lesevorgänge werden an sekundäre Repset-Mitglieder gesendet, sofern einer von ihnen verfügbar ist. Das primäre Mitglied wird ausschließlich für Schreibvorgänge verwendet, es sei denn, alle sekundären Mitglieder sind nicht mehr verfügbar. Abgesehen vom Fallback auf das primäre Mitglied für Lesevorgänge entspricht dies ReadPreference.secondary ().

  • ReadPreference.nearest () : Lesevorgänge werden an das nächste Repset-Mitglied gesendet, das dem Datenbankclient zur Verfügung steht. Nur verwenden, wenn eventuell konsistente Lesevorgänge akzeptabel sind. Das nächste Mitglied ist das Mitglied mit der geringsten Latenz zwischen dem Client und den verschiedenen Repset-Mitgliedern. Da beschäftigte Mitglieder möglicherweise höhere Latenzen haben, sollte dies auch automatisch die Leselast ausgleichen, obwohl nach meiner Erfahrung sekundäre (bevorzugte) dies besser zu tun scheint, wenn die Latenzen der Mitglieder relativ konsistent sind.

Hinweis: Alle oben genannten Versionen verfügen über tagaktivierte Versionen derselben Methode, die stattdessen TaggableReadPreference-Instanzen zurückgeben. Eine vollständige Beschreibung der Replikatsatz-Tags finden Sie hier: Replikatsatz-Tags

Remon van Vliet
quelle
6
Ist es nicht gefährlich, socketTimeout und connectTimeout als Standard (unendlich) zu belassen? Wenn eine Verbindung aus irgendeinem Grund hängt, bleibt Ihre App (oder zumindest dieser Thread) für immer hängen. Sollten diese nicht einfach als sehr sehr hoch eingestellt werden (etwa 30 Sekunden für die Verbindung, 2 Minuten für die Buchse)?
Idris Mokhtarzada
Idris, sehr wahr. In meinem Beitrag habe ich fälschlicherweise angenommen, dass MongoOptions unsere Standardeinstellungen hat. Unsere Mongo ORM-Ebene hat diese bei 15 Sekunden bzw. 1 Minute und beim Schreiben habe ich angenommen, dass dies die Standardeinstellungen sind. Unendliche Auszeiten sind definitiv eine schlechte Idee. Vielen Dank für das Heads-up, ich habe es in der Post behoben
Remon van Vliet
Die Option "SlaveOk" ist jetzt veraltet. Wenn Sie möchten, dass das Äquivalent dazu wahr ist, gehen Sie wie folgt vor: mongoOptions.readPreference = ReadPreference.secondaryPreferred ();
Gubatron
Gute Antwort, aber Ihre Definition von threadsAllowedToBlockForConnectionMultiplier ist falsch (Schlüsselwortmultiplikator). Gemäß Dokumentation: "Multiplikator für ConnectionsPerHost für die Anzahl der Threads, die blockieren können, wenn ConnectionsPerHost 10 ist, und ThreadsAllowedToBlockForConnectionMultiplier 5, dann können 50 Threads mehr als das blockieren und eine Ausnahme wird ausgelöst"
Tyler Zale
3
Scheint eine ziemlich beliebte Antwort zu sein. Wenn jemand daran interessiert ist, dass ich dies aktualisiere, um Änderungen im neuesten Treiber widerzuspiegeln, lass es mich wissen
Remon van Vliet