pgBouncer działa świetnie, ale czasami staje się niedostępny

9

Korzystam z pgBouncer przed zajętą ​​bazą danych postgres 9. Przez większość czasu działa dobrze. Ale co kilka godzin będę otrzymywać wiadomość e-mail o błędzie z mojej aplikacji z wyjątkiem psycopg2:

OperationalError („nie można połączyć się z serwerem: nie można przypisać żądanego adresu Czy serwer działa na hoście„ neo-hulk ”i akceptuje połączenia TCP / IP na porcie 6432?”)

Jest to aplikacja python z grupą pracowników selera wykonujących zadania. Po pojawieniu się tych błędów sprawdzam db pgbouncera i rozmiar puli mieści się w granicach. Po kilku eksperymentach ustawiłem maksymalny rozmiar puli na 400, a rozmiar puli na 200. Trybem puli jest „sesja” (żądania są w większości automatyczne zatwierdzania, prawie żadnych transakcji).

Co sprawia, że ​​pgBouncer „znika” w ten sposób? jest to tylko przez krótki okres czasu (w sumie mówimy o niewielkiej liczbie żądań w porównaniu do samej liczby wniosków, które są przekazywane), ale te, które się nie powiedzie, są ważne.

Dzięki!

Harel
źródło
System operacyjny i wersja? Wersja jądra, jeśli Linux? Dokładne wersje PostgreSQL i PgBouncer? Czy uruchomiłeś PgBouncer na poziomie dziennika debugowania i sprawdziłeś, czy zgłasza coś przydatnego?
Craig Ringer
Debian 6. Linux wersja 2.6.32-5-amd64 (Debian 2.6.32-48squeeze1) pgbouncer wersja 1.5.4 Postgres 9.1. Dziennik nie rejestruje łączenia / rozłączania, ponieważ myślałem, że to trochę za dużo, ale nie ma żadnych błędów podczas zgłaszania błędów aplikacji. Błąd wynika z tego, że psycopg2 uważa, że ​​nie ma serwera db, z którym mógłby rozmawiać, chociaż ten problem nie istniał przed pgbouncer
Harel
1
Hm, więc obecny PgBouncer, a jądro jest stare, ale dość stabilne. Myślę, że musisz włączyć bardziej szczegółowe logowanie w PgBouncer za pomocą -vvvi sprawdzić, czy możesz dopasować anomalne wyniki dziennika do swoich błędów w czasie.
Craig Ringer
Zrobiłem „set verbose = 1; reload;” w powłoce pgbouncera i nie mógł znaleźć niczego niezwykłego w dzienniku. jest to system produkcyjny, więc nie mógł zatrzymać usługi, aby działała jako demon inny niż -vvv. Mam nadzieję, że mam ten sam wynik. Zauważ, że błąd sugeruje, że w ogóle nie mógł się połączyć z pgbouncerem, tzn. nie mógł znaleźć tego nasłuchującego w tym porcie. Przez cały czas powstają tysiące połączeń i dziwne, że tak mała ich liczba zawodzi.
Harel
Zdradliwy; brzmi jak potencjalny stan wyścigu, ale w jakim / gdzie ...
Craig Ringer

Odpowiedzi:

15

Część „ Nie można przypisać żądanego adresu ” w komunikacie o błędzie pochodzi ze stosu TCP jądra. W przypadku napotkania sporadycznie oznacza to zazwyczaj, że przestrzeń dostępnych gniazd jest wyczerpana z powodu zbyt dużej liczby gniazd w stanie oczekiwania ( TIME_WAITlub mniej prawdopodobne FIN_WAIT_1lub FIN_WAIT_2)

Zakres portów gniazd może być wyprowadzany przez cat /proc/sys/net/ipv4/ip_local_port_range. Domyślna wartość standardowego jądra Linuksa to ogólnie 32768 61000.

Możesz sprawdzić wynik netstat -ton|grep WAITna kliencie (-ach) i na hoście pgBouncerera, gdy system jest zajęty. -oFlag pokaże liczniki czasu oczekiwania związane z państw czekać.

Jeśli łączna liczba gniazd TCP jest bliska, 61000-32768=28232prawdopodobnie wyczerpanie tego zakresu jest prawdopodobnie problemem. Ponieważ zamknięte gniazdo spędza 60 sekund w TIME_WAITstanie w normalnym stanie, jeśli host klienta łączy się więcej niż 28232 razy w ciągu jednej minuty, nowe połączenia zakończą się niepowodzeniem z wymienionym błędem, dopóki porty nie zostaną zwolnione.

Jako pierwsze obejście można rozszerzyć zakres portów TCP:

 # echo "1025 65535" >/proc/sys/net/ipv4/ip_local_port_range

Jeśli nie jest zadowalający, sprawdź flagi tcp_tw_recyclei tcp_tw_reuse, a także przestrajaj przez /proc/sys/net/ipv4i sysctl.

Są one zdefiniowane jako (z man tcp):

       tcp_tw_recycle (Boolean; domyślnie: wyłączone; od Linuksa 2.4)
              Włącz szybki recykling gniazd TIME_WAIT. Włączanie tego
              opcja nie jest zalecana, ponieważ powoduje to problemy podczas pracy
              ing z NAT (Network Address Translation).

       tcp_tw_reuse (Boolean; domyślnie: wyłączone; od Linuksa 2.4.19 / 2.6)
              Pozwól ponownie użyć gniazd TIME_WAIT do nowych połączeń, gdy jest
              bezpieczne z punktu widzenia protokołu. Nie należy tego zmieniać bez
              porady / prośby ekspertów technicznych.

Osobiście odnosiłem sukces, tcp_tw_recyclegdy miałem do czynienia z tym problemem z aplikacją kliencką MySQL, ale nie bierz tego za zalecenie, moje rozumienie TCP jest w najlepszym razie powierzchowne.

Daniel Vérité
źródło
1
Ta odpowiedź pokazuje cokolwiek powierzchownie rozumie protokół TCP. Dziękuję za to. Zwiększyłem zasięg portów i pozwoliłem mu działać przez jakiś czas, aby sprawdzić, czy ma to jakiś wpływ. (Czy muszę zrestartować komputer po jego ustawieniu?)
Harel
Wydaje mi się, że zwiększenie portów to zrobiło. Do tej pory nie otrzymałem żadnego błędu. Z grubsza liczba linii netstat pokazuje w kliencie prawie 20 KB, więc stamtąd domyślny limit 28 KB nie jest długi. Dziękuję za to!
Harel
1
Dobrze! Chcesz ustawić to ustawienie /etc/sysctl.conftak, net.ipv4.ip_local_port_range = 1025 65535aby zachowało się po ponownym uruchomieniu.
Daniel Vérité
Dzięki. Od tego czasu otrzymałem błędy, ale nie ten, więc to nadal dobrze. Pozostawienie go na kilka dni spowoduje zmianę perm. Cieszę się, że jak dotąd wydaje się to działać, ponieważ inne zmiany mnie przerażają :)
Harel