2012-01-17 15 views
21

podsumowanie problemu

jesteśmy o konfiguracji którym dużo (800 do 2400 na sekundę (z połączeń przychodzących do skrzynki Linux i mamy NAT urządzenia pomiędzy klientem a serwerem. więc w systemie pozostało tyle gniazd TIME_WAIT Aby przezwyciężyć to, ustawiliśmy tcp_tw_recycle na 1, ale to doprowadziło do spadku liczby połączeń przychodzących po przejrzeniu sieci znaleźliśmy referencje dla przyczyn upuszczenia Ramki z tcp_tw_recycle i urządzeniem NAT się zdarzająspada połączeń z tcp_tw_recycle

Rozwiązanie wypróbowane

próbowaliśmy przez ustawienie tcp_tw_reuse na 1 działało bez problemów z tą samą konfiguracją i konfiguracją.

Jednak dokumentacja mówi, że tcp_tw_recycle i tcp_tw_reuse nie powinny być używane, gdy połączenia przechodzące przez węzły świadome stanu TCP, takie jak zapory ogniowe, urządzenia NAT lub równoważenia obciążenia, mogą widzieć upuszczone ramki. Im więcej połączeń, tym bardziej prawdopodobne, że zobaczysz ten problem.

Zapytania

1) mogą być stosowane w tcp_tw_reuse tego typu scenariuszy? 2) jeśli nie, która część kodu linuksowego uniemożliwia użycie tcp_tw_reuse w takim scenariuszu? 3) ogólnie jaka jest różnica między tcp_tw_recycle i tcp_tw_reuse?

Odpowiedz

42

Domyślnie, gdy zarówno tcp_tw_reuse i tcp_tw_recycle są wyłączone, jądro będzie upewnić się, że gniazda w TIME_WAIT państwa pozostanie w tym stanie wystarczająco długo - wystarczająco długo, aby mieć pewność, że pakiety należące do przyszłych połączeń nie będą mylone późne pakiety starego połączenia.

Po włączeniu tcp_tw_reuse można używać gniazd w stanie TIME_WAIT przed ich wygaśnięciem, a jądro będzie próbowało upewnić się, że nie ma kolizji w odniesieniu do numerów sekwencji TCP. Jeśli włączysz tcp_timestamps (a.k.a. PAWS, w celu ochrony przed zawijanymi numerami sekwencji), upewni się, że te kolizje nie mogą się zdarzyć. Musisz jednak włączyć sygnatury czasowe TCP na , oba kończą się (przynajmniej tak rozumiem). Zobacz definition of tcp_twsk_unique, aby poznać szczegóły.

Po włączeniu tcp_tw_recycle jądro staje się znacznie bardziej agresywne, a także przyjmuje założenia dotyczące znaczników czasu używanych przez hosty zdalne. Śledzi on ostatni znacznik czasu używany przez każdy zdalny host mający połączenie w stanie TIME_WAIT) i pozwala na ponowne użycie gniazda, jeśli znacznik czasu został poprawiony. Jeśli jednak znacznik czasu używany przez hosta ulegnie zmianie (tj. Cofnie się w czasie), pakiet SYN zostanie po cichu upuszczony, a połączenie nie zostanie nawiązane (pojawi się błąd podobny do "timeout połączenia"). Jeśli chcesz zanurkować w kodzie jądra, dobrym początkiem może być definition of tcp_timewait_state_process.

Teraz sygnatury czasowe nie powinny cofać się w czasie; chyba że:

  • host zostanie uruchomiony ponownie (ale potem, do czasu wraca do góry, TIME_WAIT gniazdo prawdopodobnie wygasł, więc będzie to nie problem);
  • adres IP jest szybko ponownie wykorzystywany przez coś innego (TIME_WAIT połączenia pozostaną trochę, ale inne połączenia prawdopodobnie zostaną trafione przez TCP RST i to zwolni trochę miejsca);
  • tłumaczenie adresu sieciowego (lub firewall smarty-pants) jest zaangażowany w środku połączenia.

W tym ostatnim przypadku można mieć wiele hostów za tym samym adresem IP, a zatem różne sekwencje znaczników czasowych (lub wspomniane znaczniki czasowe są losowane przy każdym połączeniu przez zaporę). W takim przypadku niektóre hosty będą losowo niezdolne do połączenia, ponieważ są odwzorowane na port, dla którego na wiadro serwera znajduje się nowszy znacznik czasu. Dlatego dokumenty mówią ci, że "urządzenia NAT lub load balancery mogą uruchamiać ramki upuszczania z powodu ustawienia".

Niektórzy ludzie zalecają pozostawienie tcp_tw_recycle osobno, ale włącz tcp_tw_reuse i niższą . Zgadzam się :-)

+6

Łącze na dole złamane – nhed

+0

Wielkie dzięki. Napotkałem właśnie ten przypadek - hosty za NATem będą losowo niezdolne do połączenia, a wyłączenie net.ipv4.timestamps właśnie dostanie wszystko dobrze (tcp_tw_recycle i tcp_tw_reuse są włączone na obu komputerach). – Yurii

+1

Wierzę, że powinno to być 'tcp_fin_timeout', a nie' tcp_timewait_len'. Ale może zmieniło się to w wersjach jądra? – Trendfischer

Powiązane problemy