Jak zdecydowano o tych domyślnych ustawieniach Linux-a TCP?

13

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_time2 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ę psqlsesję 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ń.

Josh Kupershmidt
źródło
Kilka istotnych informacji tutaj ... tldp.org/HOWTO/TCP-Keepalive-HOWTO/usingkeepalive.html
Drav Sloan
Pamiętaj, że możesz zmienić pierwszy trzy per-połączenia w kodzie klienta za pomocą opcji gniazda TCP_KEEPIDLE, TCP_KEEPCNTi TCP_KEEPINTVL.
wnoise,
1
@wnoise faktycznie od Linuksa 2.6.37 powinno być również możliwe określenie opcji gniazda TCP_USER_TIMEOUT, zamiast ustawiania net.ipv4.tcp_retries2całego systemu. Oczywiście wiele aplikacji (takich jak PostgreSQL w moim przykładzie tutaj) nie jest TCP_USER_TIMEOUTjeszcze obsługiwanych .
Josh Kupershmidt,

Odpowiedzi:

6

RFC 1122 określa w sekcji 4.2.3.6, że okres utrzymywania przy życiu nie może przekraczać dwóch godzin.

wnoise
źródło
1
Fajnie, dziękuję za wykopanie tego. Myślę, że to głównie odpowiada na pytanie, dlaczego tcp_keepalive_timedomyślna wartość to 7200, choć nadal byłbym zainteresowany precedensem / wyjaśnieniem pozostałych trzech istotnych ustawień.
Josh Kupershmidt,
Usuwanie mojej odpowiedzi, ponieważ to odpowiada na pytanie (przynajmniej dla jednej z wartości)
coteyr
1
@coteyr W każdym razie dziękuję, doceniam wysiłek. IIRC był intrygujący komentarz do twojej odpowiedzi sugerujący, że we wcześniejszych jądrach Linuksa domyślnie było to 15 minut. Byłbym zainteresowany tym, jak / dlaczego zmieniono to na 2 godziny lub w pierwszej kolejności na 15 minut.
Josh Kupershmidt,