Spędziłem ostatnio sporo czasu na śledzeniu problemu w produkcji, gdy zniknięcie serwera bazy danych spowodowałoby zawieszenie się do 2 godzin (długie oczekiwanie na poll()
połączenie w bibliotece klienta libpq) dla podłączonego klienta. Zagłębiając się w problem, zdałem sobie sprawę, że te parametry jądra powinny zostać obniżone, aby odcięte połączenia TCP były zauważane w odpowiednim czasie:
net.ipv4.tcp_keepalive_time = 7200
net.ipv4.tcp_keepalive_probes = 9
net.ipv4.tcp_keepalive_intvl = 75
net.ipv4.tcp_retries2 = 15
Cztery powyższe wartości pochodzą z komputera z systemem Ubuntu 12.04 i wygląda na to, że te wartości domyślne nie uległy zmianie od bieżących wartości domyślnych jądra Linux .
Ustawienia te wydają się być bardzo tendencyjne do utrzymywania otwartego połączenia i są wyjątkowo skąpe w przypadku czujników utrzymujących aktywność. AIUI, domyślnie tcp_keepalive_time
2 godziny oznaczają, że kiedy czekamy na odpowiedź dla zdalnego hosta, będziemy cierpliwie czekać 2 godziny przed zainicjowaniem sondy podtrzymującej, aby sprawdzić, czy nasze połączenie jest nadal prawidłowe. A następnie, jeśli zdalny host nie zareaguje na sondę podtrzymującą działanie, ponawiamy próbę działania tych czujników 9 razy ( tcp_keepalive_probes
), w odstępie 75 sekund ( tcp_keepalive_intvl
), więc jest to dodatkowe 11 minut, zanim zdecydujemy, że połączenie naprawdę nie działa.
Jest to zgodne z tym, co widziałem w tej dziedzinie: na przykład, jeśli rozpocznę psql
sesję połączoną ze zdalną instancją PostgreSQL, z pewnym zapytaniem oczekującym na odpowiedź, np.
SELECT pg_sleep(30);
a następnie zdalny serwer umiera okropną śmiercią (np. upuszcza ruch na tę maszynę), widzę, że moja sesja psql czeka do 2 godzin i 11 minut, zanim zorientuje się, że połączenie jest zerwane. Jak można sobie wyobrazić, te domyślne ustawienia powodują poważne problemy z kodem, który rozmawiamy z bazą danych podczas, powiedzmy, zdarzenia przełączenia awaryjnego bazy danych. Obniżenie tych pokręteł bardzo pomogło! I widzę, że nie jestem sam w zalecaniu dostosowania tych wartości domyślnych.
Więc moje pytania to:
- Jak długo trwają takie wartości domyślne?
- Jakie było pierwotne uzasadnienie dla ustawienia tych ustawień TCP jako domyślnych?
- Czy jakieś dystrybucje Linuksa zmieniają te wartości domyślne?
Doceniamy każdą inną historię lub perspektywę uzasadnienia tych ustawień.
TCP_KEEPIDLE
, TCP_KEEPCNT
i TCP_KEEPINTVL
.
TCP_USER_TIMEOUT
, zamiast ustawiania net.ipv4.tcp_retries2
całego systemu. Oczywiście wiele aplikacji (takich jak PostgreSQL w moim przykładzie tutaj) nie jest TCP_USER_TIMEOUT
jeszcze obsługiwanych .