2016-01-06 15 views
5

Moja aplikacja internetowa Python ma kilka połączeń zarejestrowanych na tym samym serwerze MongoDb, ale 3 różne bazy danych. Aplikacja prowadzona jest pod 4 pracownikami Gunicorn.Blokuj, dopóki nie zostanie skonfigurowana nowa konfiguracja zestawu replik

Używam zestawu replik.

Gdy podstawowy jest wyłączony, prąd kwerenda nie powiedzie i odświeżania jest zaplanowane w MongoReplicaSetClient (2.8, ale myślę, że w 3.2 jest taka sama). Następne zapytanie może się powieść, jeśli do czasu zostanie wybrany nowy element główny, a program MonitorThread otrzyma informacje o aktualizacji połączenia klienta.

Ale odświeżenie dotyczy tylko tego klienta. Inni klienci podłączeni do tego samego serwera MongoDB nie mają wpływu - ta sama historia dzieje się z każdym. Oznacza to, że jeśli każdy pracownik jest podłączony do 3 baz danych na tym samym serwerze MongoDB i powtarzam to samo żądanie HTTP, które używa wszystkich 3 baz danych, gdy podstawowy nie powiedzie się, aktualizację wszystkich podłączonych klientów zajmuje nieokreślony czas. Jeśli każde żądanie HTTP przechodzi w trybie round-robin do każdego pracownika na 4, potrzebujemy 12 żądań aktualizacji każdego klienta Mongo. Ale w rzeczywistości prośby nie idą dookoła.

Patrząc na kod PyMongo MongoReplicaSetClient._send_message_with_response widzę, że gdy podstawowy jest w dół, self.disconnect nazywa który nazywa self.__schedule_refresh. Ta metoda ma argument sync, który umożliwia "blokowanie do zakończenia odświeżania".

Mój pomysł to złapać wyjątek AutoReconnect i zadzwonić pod numer __schedule_refresh(sync=True) na wszystkich klientach, którzy są połączeni z uszkodzonym podstawowym i blokowym, dopóki nie zostanie skonfigurowana nowa konfiguracja zestawu replik. Więc żądania HTTP nie będą przetwarzane (co daje 500) dopóki baza danych nie będzie w porządku.

Ale __schedule_refresh to prywatna metoda. Również nie wiem, czy wywołanie go sekwencyjnie na wszystkich klientach będzie szybkie - wygląda MonitorThread wykonuje swoją pracę w odstępach czasu.

A może mógłbym użyć MongoReplicaSetClient.refresh.

Co sądzisz o tym pomyśle? Czy ma wady?

Pomożesz mi we wdrożeniu?

Odpowiedz

0

interesujący problem.

jeśli pracujesz w środowisku, gdzie wiele żądań są w najbliższych, chciałbym zaproponować przed mając każdy pracownik blok na IO, a zwłaszcza połączenia sieciowego, jak czeka na podstawowym celu wymyślić.

proponuję próbuje przechwytywać wyjątki od klienta Mongo, co może wskazywać, że serwer jest w dół i powrót 503s do rozmówcy. 503 są na ogół dobrym sposobem na poinformowanie, że zasób jest niedostępny i sugerowanie ponownej próby w późniejszym czasie.

baza danych Mongo będzie zejść podczas użytkowania i posiadające appserver wykryć to, zrzucić żądania i powrócić 503s jest jednym ze sposobów, aby obsłużyć ruch, który w przeciwnym razie zaczną blokowanie, zabraknie wątków i zabić appserver. kazać administratorowi rzucić wszystkie te połączenia, które skutkowałyby oczekiwaniem i możliwą awarią.

jest to wspólny idiom wykorzystywane przy świadczeniu usług REST: http://www.restpatterns.org/HTTP_Status_Codes/503_-_Service_Unavailable

można jeszcze dodać „Retry-After” nagłówku w celu wskazania, gdy klient powinien próbować się powtórzenie w przyszłości. trochę więcej informacji na nagłówek Retry-After i jak niektóre przeglądarki interpretują go:

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

HTH

Powiązane problemy