Django: CONN_MAX_AGE utrzymuje połączenia, ale nie używa ich ponownie z PostgreSQL

17

Mam konfigurację django używającą Django 1.6.7 i Postgres 9.3 na Ubuntu 14.04 LTS.

W dowolnym momencie strona uzyskuje około 250 jednoczesnych połączeń z bazą danych PostgreSQL, która jest czterordzeniowym procesorem Xeon E5-2670 o częstotliwości 2,5 GHz i ma 16 GB pamięci RAM. Przeciętne obciążenie tej konkretnej maszyny w ciągu dnia wynosi około 20 do 30.

Czasami dostaję e-maile z wartownikami o przekroczeniu limitu czasu połączeń z bazą danych, i myślę, że włączenie pewnego rodzaju puli połączeń pomoże złagodzić ten problem, a także nieco zmniejszyć obciążenie bazy danych.

Ponieważ używamy Django 1.6, mamy do dyspozycji wbudowane buforowanie. Jednak gdy ustawię CONN_MAX_AGE na 10 sekund lub 60 sekund, prawie natychmiast liczba jednoczesnych połączeń przeskakuje do maksymalnego dozwolonego ustawienia (około dwa razy więcej niż zwykle), a połączenia zaczynają być odrzucane.

Wygląda więc na to, że z jakiegokolwiek powodu połączenia utrzymujące, ale NIE SĄ ponownie używane.

Co może być przyczyną tego?

PS. Używamy również gunicorn z opcją --worker-class = eventlet. Może to jest źródło naszych nieszczęść?

synic
źródło

Odpowiedzi:

18

W trakcie dalszych eksperymentów odkryłem, że przyczyną naszego problemu była klasa robotników eventletów gunicorn. Każdy mikroprocesor tworzył własne trwałe połączenie i nie było możliwości ponownego użycia żadnego z nich.

Wyłączenie eventletu spowodowało wzrost obciążenia naszych serwerów (ale nie o wiele), ale obciążenie postgresu spadło teraz średnio do 3. Z 30.

synic
źródło
2
Właśnie zaoszczędziłeś nam mnóstwo czasu! Obserwujemy dokładnie to samo zachowanie i używamy eventletu. Spróbuje przełączyć się na pule połączeń i zobaczyć, jak to będzie działać.
silentser
3
Aktualizacja: łączenie połączeń z bazą danych za pomocą pgBouncer wydawało się rozwiązać problem (nadal korzystamy z eventletu)
silentser
Najwyraźniej jest też psycogreen: pypi.python.org/pypi/psycogreen/1.0 (nie próbowałem tego, ponieważ kiedy ustawię CONN_MAX_AGE na zero, nasz system potrzebuje 20ms na połączenie DB, więc po prostu nie potrzebujemy pulowania)
Darren
1
Google zajęło mi trochę czasu, aby znaleźć odpowiedź na ten sam problem, który mieliśmy.
Alper