Jak skonfigurować sterownik MongoDB Java MongoOptions do użytku produkcyjnego?


100

Szukałem w Internecie najlepszych praktyk dotyczących konfigurowania MongoOptions dla sterownika MongoDB Java i nie wymyśliłem nic poza API. To wyszukiwanie rozpoczęło się po tym, jak natrafiłem na błąd „com.mongodb.DBPortPool $ SemaphoresOut: Brak semaforów, aby uzyskać połączenie bazy danych” i przez zwiększenie połączeń / mnożnika udało mi się rozwiązać ten problem. Szukam linków do lub twoich najlepszych praktyk w konfigurowaniu tych opcji do produkcji.

Opcje sterownika 2.4 obejmują: http://api.mongodb.org/java/2.4/com/mongodb/MongoOptions.html

  • autoConnectRetry
  • połączeniaPerHost
  • connectTimeout
  • maxWaitTime
  • socketTimeout
  • threadAllowedToBlockForConnectionMultiplier

Nowsze sterowniki mają więcej opcji i też chciałbym o nich usłyszeć.

Odpowiedzi:


160

Zaktualizowano do 2.9:

  • autoConnectRetry oznacza po prostu, że sterownik będzie automatycznie próbował ponownie połączyć się z serwerem (serwerami) po nieoczekiwanym rozłączeniu. W środowiskach produkcyjnych zwykle chcesz, aby ta wartość była włączona.

  • PołączeniaPerHost to liczba fizycznych połączeń, które pojedyncza instancja Mongo (jest to singleton, więc zwykle masz jedno na aplikację) może nawiązać z procesem mongod / mongos. W chwili pisania tego tekstu sterownik java ostatecznie ustali taką liczbę połączeń, nawet jeśli rzeczywista przepustowość zapytań jest niska (w kolejności słów zobaczysz statystykę „conn” we wzroście mongostatu, aż osiągnie tę liczbę na serwer aplikacji).

    W większości przypadków nie ma potrzeby ustawiania wartości większej niż 100, ale to ustawienie jest jedną z rzeczy „przetestuj i zobacz”. Zauważ, że będziesz musiał upewnić się, że ustawiłeś to wystarczająco nisko, aby całkowita liczba połączeń z twoim serwerem nie przekroczyła

    db.serverStatus().connections.available

    W produkcji mamy obecnie 40 lat.

  • connectTimeout . Jak sama nazwa wskazuje, ile milisekund sterownik będzie czekał, zanim próba połączenia zostanie przerwana. Ustaw limit czasu na długi (15-30 sekund), chyba że istnieje realistyczna, spodziewana szansa, że ​​będzie to przeszkodą w udanych próbach połączenia. Zwykle, jeśli próba połączenia trwa dłużej niż kilka sekund, infrastruktura sieciowa nie jest w stanie zapewnić wysokiej przepustowości.

  • maxWaitTime . Liczba ms, przez które wątek będzie czekał, aż połączenie stanie się dostępne w puli połączeń, i zgłasza wyjątek, jeśli nie nastąpi to na czas. Zachowaj domyślne.

  • socketTimeout . Standardowa wartość limitu czasu gniazda. Ustaw na 60 sekund (60000).

  • threadAllowedToBlockForConnectionMultiplier . Mnożnik dla połączeń connectionsPerHost oznaczający liczbę wątków, które mogą czekać na udostępnienie połączeń, jeśli pula jest aktualnie wyczerpana. To jest ustawienie, które spowoduje wyjątek „com.mongodb.DBPortPool $ SemaphoresOut: Brak semaforów, aby uzyskać połączenie z bazą danych”. Ten wyjątek zostanie zgłoszony, gdy kolejka wątków przekroczy wartość ThreadAllowedToBlockForConnectionMultiplier. Na przykład, jeśli connectionPerHost wynosi 10, a ta wartość wynosi 5, do 50 wątków może zostać zablokowanych przed zgłoszeniem wspomnianego wyjątku.

    Jeśli spodziewasz się dużych skoków przepustowości, które mogą powodować duże kolejki, tymczasowo zwiększ tę wartość. W tej chwili mamy go na 1500 właśnie z tego powodu. Jeśli obciążenie zapytania konsekwentnie przewyższa serwer, należy po prostu odpowiednio poprawić stan sprzętu / skalowania.

  • readPreference . (AKTUALIZACJA, 2.8+) Służy do określania domyślnych preferencji odczytu i zastępuje „slaveOk”. Skonfiguruj ReadPreference za pomocą jednej z metod fabryki klas. Pełny opis najczęściej używanych ustawień można znaleźć na końcu tego postu

  • w . (AKTUALIZACJA, 2.6+) Ta wartość określa „bezpieczeństwo” zapisu. Gdy ta wartość wynosi -1, zapis nie zgłosi żadnych błędów, niezależnie od błędów sieci lub bazy danych. WriteConcern.NONE jest odpowiednią predefiniowaną wartością WriteConcern. Jeśli w ma wartość 0, wówczas błędy sieciowe spowodują niepowodzenie zapisu, ale błędy mongo nie. Jest to zwykle nazywane zapisami „odpal i zapomnij” i powinno być używane, gdy wydajność jest ważniejsza niż spójność i trwałość. Użyj WriteConcern.NORMAL dla tego trybu.

    Jeśli ustawisz w na 1 lub więcej, zapis jest uważany za bezpieczny. Bezpieczne zapisy wykonują zapis i następują po nim żądanie do serwera, aby upewnić się, że zapis się powiódł lub pobrać wartość błędu, jeśli tak się nie stało (innymi słowy, wysyła polecenie getLastError () po zapisaniu). Zwróć uwagę, że dopóki polecenie getLastError () nie zostanie zakończone, połączenie jest zarezerwowane. W wyniku tego i dodatkowego polecenia przepustowość będzie znacznie niższa niż w przypadku zapisów z w <= 0. Z wartością aw równą dokładnie 1, MongoDB gwarantuje, że zapis powiódł się (lub nie powiódł się w sposób weryfikowalny) w instancji, do której został wysłany.

    W przypadku zestawów replik możesz użyć wyższych wartości dla w, które powiedz MongoDB, aby wysłał zapis do przynajmniej "w" członków zestawu replik przed zwróceniem (lub dokładniej, poczekaj na replikację twojego zapisu do członków "w" ). Możesz również ustawić w jako łańcuch „większość”, który mówi MongoDB, aby wykonywał zapis do większości składowych zestawu replik (WriteConcern.MAJORITY). Zazwyczaj należy ustawić tę wartość na 1, chyba że potrzebujesz surowej wydajności (-1 lub 0) lub replikowanych zapisów (> 1). Wartości wyższe niż 1 mają znaczny wpływ na przepustowość zapisu.

  • fsync . Opcja trwałości, która zmusza mongo do opróżnienia dysku po każdym zapisie, gdy jest włączona. Nigdy nie miałem żadnych problemów z trwałością związanych z zaległościami zapisu, więc mamy to na false (domyślnie) w produkcji.

  • j * (NOWOŚĆ 2.7+) *. Wartość logiczna, która po ustawieniu wartości true zmusza MongoDB do oczekiwania na pomyślne zatwierdzenie grupy dziennika przed powrotem. Jeśli masz włączone księgowanie, możesz je włączyć, aby zwiększyć trwałość. Zapoznaj się z http://www.mongodb.org/display/DOCS/Journaling, aby zobaczyć, jakie dziennikowanie daje (i dlaczego warto włączyć tę flagę).

ReadPreference Klasa ReadPreference umożliwia skonfigurowanie, do jakich instancji mongod kierowane są zapytania, jeśli pracujesz z zestawami replik. Dostępne są następujące opcje:

  • ReadPreference.primary () : Wszystkie odczyty trafiają tylko do podstawowego elementu członkowskiego repset. Użyj tego, jeśli chcesz, aby wszystkie zapytania zwracały spójne (ostatnio zapisane) dane. To jest ustawienie domyślne.

  • ReadPreference.primaryPreferred () : wszystkie odczyty trafiają do podstawowego elementu członkowskiego repset, jeśli to możliwe, ale mogą wysyłać zapytania do drugorzędnych elementów członkowskich, jeśli węzeł podstawowy nie jest dostępny. W związku z tym, jeśli podstawowy staje się niedostępny, odczyty stają się ostatecznie spójne, ale tylko wtedy, gdy podstawowy jest niedostępny.

  • ReadPreference.secondary () : Wszystkie odczyty trafiają do drugorzędnych elementów członkowskich repset, a podstawowy element członkowski jest używany tylko do zapisu. Używaj tego tylko wtedy, gdy możesz żyć z ostatecznie spójnymi odczytami. Dodatkowych członków powtórzeń można użyć do zwiększenia wydajności czytania, chociaż istnieją ograniczenia co do liczby członków (głosujących), które może mieć powtórzenie.

  • ReadPreference.secondaryPreferred () : wszystkie odczyty trafiają do drugorzędnych członków repset, jeśli którykolwiek z nich jest dostępny. Podstawowy element członkowski jest używany wyłącznie do zapisów, chyba że wszyscy drugorzędni członkowie staną się niedostępni. Inaczej niż w przypadku powrotu do podstawowego elementu członkowskiego do odczytu, jest to to samo, co ReadPreference.secondary ().

  • ReadPreference.nearest () : odczyty przechodzą do najbliższego członka repset dostępnego dla klienta bazy danych. Używaj tylko, jeśli ostatecznie spójne odczyty są dopuszczalne. Najbliższy członek to członek z najmniejszym opóźnieniem między klientem a różnymi członkami powtórzeń. Ponieważ zajęci członkowie w końcu będą mieli większe opóźnienia, powinno to również automatycznie zrównoważyć obciążenie odczytu, chociaż z mojego doświadczenia wynika, że ​​drugorzędne (preferowane) wydają się to robić lepiej, jeśli opóźnienia elementów są względnie spójne.

Uwaga: wszystkie powyższe mają wersje tej samej metody z włączonymi tagami, które zamiast tego zwracają wystąpienia TaggableReadPreference. Pełny opis oznaczeń zestawów replik można znaleźć tutaj: Tagi zestawów replik


6
Czy pozostawienie opcji socketTimeout i connectTimeout jako domyślnej (nieskończonej) nie jest niebezpieczne? Jeśli z jakiegoś powodu połączenie się zawiesi, Twoja aplikacja (lub przynajmniej ten wątek) utknie na zawsze. Czy nie powinny one być ustawione jako bardzo wysokie (około 30 sekund na połączenie, 2 minuty na gniazdo)?
Idris Mokhtarzada

Idris, bardzo prawda. W moim poście błędnie założyłem, że MongoOptions ma nasze wartości domyślne. Nasza warstwa Mongo ORM ma te wartości odpowiednio po 15 sekundach i 1 minucie i podczas pisania założyłem, że są to wartości domyślne. Nieskończone limity czasu to zdecydowanie zły pomysł. Dzięki za ostrzeżenie, poprawiłem to w poście
Remon van Vliet

opcja „slaveOk” jest teraz przestarzała, jeśli chcesz, aby jej odpowiednik był prawdziwy, wykonaj: mongoOptions.readPreference = ReadPreference.secondaryPreferred ();
Gubatron,

Dobra odpowiedź, ale Twoja definicja ThreadAllowedToBlockForConnectionMultiplier jest nieprawidłowa (mnożnik słowa kluczowego). Zgodnie z dokumentacją: „mnożnik dla połączeńPerHost dla # wątków, które mogą blokować, jeśli connectionPerHost wynosi 10, a wątkiAllowedToBlockForConnectionMultiplier wynosi 5, wtedy 50 wątków może blokować więcej i zostanie wyrzucony wyjątek”
Tyler Zale

3
Wydaje się, że jest to dość popularna odpowiedź. Jeśli ktoś jest zainteresowany aktualizacją tego, aby odzwierciedlić zmiany w najnowszym sterowniku, daj mi znać
Remon van Vliet
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.