2016-01-06 10 views
5

Meine Python-Webanwendung verfügt über mehrere Verbindungen, die auf demselben MongoDb-Server registriert sind, jedoch drei verschiedene Datenbanken. Die Anwendung läuft unter 4 Gunicorn-Mitarbeitern.Blockieren, bis die Konfiguration des neuen Replikatsatzes erfolgreich ist

Ich verwende ein Replikat-Set.

Wenn das primäre heruntergefahren ist, schlägt die aktuelle Abfrage fehl und eine Aktualisierung wird in MongoReplicaSetClient (2.8 geplant, aber ich denke in 3.2 ist es das gleiche). Die nächste Abfrage ist möglicherweise erfolgreich, wenn bis zu diesem Zeitpunkt eine neue Primärdatenbank ausgewählt wird und MonitorThread Informationen darüber erhält, wie die Verbindung des Clients aktualisiert wird.

Die Aktualisierung betrifft jedoch nur diesen Client. Andere Clients, die mit demselben MongoDB-Server verbunden sind, sind nicht betroffen - mit jedem geschieht die gleiche Geschichte. Das bedeutet, dass, wenn jeder Worker mit 3 Datenbanken auf demselben MongoDB-Server verbunden ist und ich dieselbe HTTP-Anfrage wiederhole, die alle 3 Datenbanken verwendet, wenn eine primäre fehlschlägt, dauert es unbestimmte Zeit, alle verbundenen Clients zu aktualisieren. Wenn jede HTTP-Anfrage an jeden von vier Routern round-robiniert wird, benötigen wir 12 Anfragen, um jeden Mongo-Client zu aktualisieren. Aber in Wirklichkeit gehen die Anfragen nicht um.

Blick in PyMongo Code MongoReplicaSetClient._send_message_with_response Ich sehe, dass, wenn der primäre ausfällt, self.disconnect genannt wird, die self.__schedule_refresh nennt. Diese Methode hat das Argument sync, das erlaubt "zu blockieren, bis die Aktualisierung abgeschlossen ist".

Meine Idee ist zu fangen AutoReconnect Ausnahme und Anruf __schedule_refresh(sync=True) auf allen Clients, die mit der fehlgeschlagenen primären verbunden sind und blockieren, bis die neue Replikat-Set-Konfiguration vorhanden ist. Daher werden HTTP-Anfragen nicht verarbeitet (was zu 500 führt), bis die Datenbank in Ordnung ist.

Aber __schedule_refresh ist eine private Methode. Auch ich weiß nicht, ob es sequentiell auf allen Klienten anschnallt, wird schnell sein - sieht MonitorThread seine Arbeit in Intervallen aus.

Oder vielleicht könnte ich MongoReplicaSetClient.refresh verwenden.

Was denken Sie über die Idee? Hat es Nachteile?

Würdest du mir bei der Implementierung helfen?

Antwort

0

interessantes Problem.

, wenn Sie in einer Umgebung laufen, wo viele Anfragen in kommen, würde ich gegen vorschlägt jeden Arbeitnehmer Block auf IO mit, vor allem ein Netzwerk Anruf wie für ein primären warten zu kommen.

Ich würde vorschlagen, versuchen, Ausnahmen von Ihrem Mongo-Client zu erfassen, die darauf hinweisen könnten, dass der Server heruntergefahren ist und 503s an den Anrufer zurückgeben. 503s sind im Allgemeinen ein guter Weg, um zu kommunizieren, dass eine Ressource nicht verfügbar ist, und um eine Wiederholung zu einem späteren Zeitpunkt vorzuschlagen.

Ihre Mongo Datenbank wird während des Gebrauchs nach unten gehen und mit der appserver dies erkennen, Dump die Anfrage und das Rück 503s ist ein Weg, um Verkehr zu behandeln, die sonst blockiert würde starten, führen Sie den appserver aus Fäden und töten. Lassen Sie den AppServer all diese Anrufe verwerfen, die zu einem Warten und einem möglichen Ausfall führen würden.

dies ist ein gemeinsames Idiom in REST-Diensten verwendet: http://www.restpatterns.org/HTTP_Status_Codes/503_-_Service_Unavailable

Sie können auch hinzufügen, ein 'Retry-After' Header, um anzuzeigen, wenn der Client eine Wiederholung in Zukunft versuchen. einige weitere Informationen über den Retry-After-Header und wie einige Browser interpretieren:

Retry-after HTTP response header - does it affect anything?

HTH

Verwandte Themen