NFsec Logo

Retransmisje TCP

19/05/2017 w Administracja Brak komentarzy.  (artykuł nr 610, ilość słów: 990)

C

o się może złego dziać, jeśli czasy połączeń i odpowiedzi pomiędzy daemonami lub aplikacjami umieszczonymi na różnych serwerach losowo wahają się dochodząc nawet do wartości sekund? W dodatku liczba pakietów opuszczających serwer na wyjściu jest zauważalnie większa niż otrzymuje on do przetworzenia na wejściu. Wykluczając problemy wydajnościowe dotyczące utylizacji zasobów serwera, do którego się łączymy – pozostaje tylko jedno – sieć.

Jeśli do komunikacji wykorzystujemy protokół TCP/IP warto monitorować jego “zdrowie”. Jedną z kluczowych metryk tego protokołu jest liczba retransmisji występujących w systemie operacyjnym. Koncepcja retransmisji jest jednym z fundamentalnych powodów dlaczego TCP jest “niezawodny”. Po wysłaniu pakietu, jeśli nie zostanie on potwierdzony w czasie przewidzianym przez RTO (Retransmission Timeout) – system wysyłający pakiet uznaje, że wystąpił jakiś problem (np. utrata pakietu, wyczerpany bufor odbierającego systemu operacyjnego, saturacja sieci itp.) i retransmituje pakiet. RFC 793 opisuje to tak:

Kiedy TCP przesyła segment zawierający dane, tworzy jego kopię w kolejce retransmisji i uruchamia stoper; gdy otrzyma potwierdzenie dla tego segmentu – jest on usuwany z kolejki. Jeśli potwierdzenie nie zostanie odebrane przez upływem czasu, segment jest retransmitowany.

Dodatkowo istnieje jeszcze rozszerzenie protokołu TCP, które zmniejsza czas oczekiwania nadawcy przed ponownym przesłaniem utraconego segmentu – szybka retransmisja (ang. fast retransmit). Na czym polega ten mechanizm? Opiera się na zduplikowanych potwierdzeniach: po otrzymaniu pakietu (np. z numerem sekwencyjnym = 1), odbiorca wysyła potwierdzenie otrzymania pakietu dodając do numeru sekwencyjnego +1, więc = 2 – oznacza to, że odbiorca otrzymał pakiet numer 1 i oczekuje pakietu numer 2 od wysyłającego. Załóżmy teraz, że trzy kolejne pakiety zostały utracone (2,3,4). W międzyczasie odbiorca otrzymuje pakiety oznaczone sekwencjami 5 i 6. Po trzymaniu 5’tego pakietu odbiorca wysyła potwierdzenie, ale nadal z numerem sekwencyjnym równym 2. Po otrzymaniu 6’tego pakietu odbiorca nadal wysyła potwierdzenie z numerem sekwencyjnym równym 2. Ponieważ wysyłający otrzymał więcej niż jedno potwierdzenie z tym samym numerem sekwencyjnym ( = 2 w tym przykładzie) zaszło zjawisko zduplikowanego potwierdzenia (ang. duplicate acknowledgement). Jeśli nadawca otrzyma określoną liczbę potwierdzeń (zazwyczaj równą trzy lub więcej) z tymi samymi numerami sekwencyjnymi może być pewny, że ten segment danych został zagubiony i nie osiągnął celu. Nadawca więc będzie retransmitować tylko ten pakiet, który został przypuszczalnie zgubiony nie czekając na wygaśnięcie RTO. Dopiero do otrzymaniu potwierdzenia dla retransmitowanego segmentu wysyłane są kolejne pakiety.

Od wersji jądra 3.5 w Linuksie udostępniono kolejne rozszerzenie TCP – wczesne retransmisje (ang. early retransmitRFC 5827) pozwalające w pewnych warunkach na wyzwolenie szybkiej retransmisji w celu zmniejszenia liczy powtórzeń potwierdzeń. Pozwala to również warstwie transportu na użycie szybkiego retransmitowania, aby odzyskać stracone segmenty, które w normalnym przypadku wymagałyby długiego czasu zwłoki (wygaśnięcie RTO) do wykonania retransmisji. Innymi słowy, dzięki temu rozwiązaniu połączenia odzyskują utracone pakiety szybciej, co poprawia opóźnienie w komunikacji. W celu zgłębienia większej ilości wiedzy o dokładnym działaniu retransmisji i innych jej rodzajach (np. dla pakietów SYN i SYN/ACK) w systemie Linux odsyłam do artykułu Mikhaila Morfikova – Retransmisja i duplikaty pakietów w TCP.

Skoro już wiemy, że zjawisko retransmisji w sieci TCP/IP jest czymś naturalnym – jedyną rzeczą, jaka powinna nas martwić to skala tego zjawiska. Dlaczego? Ponieważ dla aplikacji (np. napisanych w Javie) retransmisje zachodzące w systemie operacyjnym są transparentne. Nie wywołują żadnego błędu i nie są zgłaszane przez libc. Więc aplikacja może pisać do gniazda sieciowego, a gdy dojdzie co jakiś czas do straty pakietu i retransmisji możemy zaobserwować opóźnienia. Jeśli chcemy monitorować podstawową ilość “wolnych” retransmisji wystarczy, że do dowolnego systemu monitoringu będziemy cyklicznie wysyłać wynik polecenia:

netstat -st | grep -i 'segments retransmited' | awk '{print $1}'

Bardziej szczegółowe dane możemy wyciągnąć z pliku /proc/net/netstat. Posiadając już informacje o skali zjawiska retransmisji wypada zidentyfikować, które aplikacje lub daemony są nim dotknięte. Zamiast nagrywać pliki .pcap za pomocą tcpdump i później analizować je w programie Wireshark możemy wykorzystać skrypt tcpretrans, który w czasie rzeczywistym pokaże nam pomiędzy jakimi adresami występują zaniki łączności:

TIME     PID    LADDR:LPORT          -- RADDR:RPORT          STATE
23:33:17 0      10.11.194.12:5568    R> 10.12.193.48:6379    ESTABLISHED
23:33:17 0      10.11.194.12:5568    R> 10.12.193.48:6379    ESTABLISHED
23:33:17 0      10.11.194.12:5568    R> 10.12.193.48:6379    ESTABLISHED
23:33:17 0      10.11.194.12:5568    R> 10.12.193.48:6379    ESTABLISHED
23:33:17 0      10.11.194.12:5568    R> 10.12.193.48:6379    ESTABLISHED
23:33:17 0      10.11.194.12:5568    R> 10.12.193.48:6379    ESTABLISHED
23:33:17 0      10.11.194.12:5568    R> 10.12.193.48:6379    ESTABLISHED
23:33:17 0      10.11.194.12:5568    R> 10.12.193.48:6379    ESTABLISHED
23:33:17 0      10.11.194.12:5568    R> 10.12.193.48:6379    ESTABLISHED
23:33:17 0      10.11.194.12:5568    R> 10.12.193.48:6379    ESTABLISHED
...

Na powyższym przykładzie może tego nie widać (ze względu na ilość reszta została ucięta), ale w ciągu sekundy nastąpiło 50 retransmisji z lokalnej aplikacji do serwera redis nasłuchującego na porcie :6379. Skala ilości retransmisji zdecydowanie przekraczała “zdrową” ilość – osiągając na niektórych serwerach ~3700/min = 61/sec. Po wstępnej analizie topologii sieci została postawiona diagnoza i decyzja o przeniesieniu 50% serwerów redis “bliżej” aplikacji, aby potwierdzić tezę wadliwej komunikacji po drodze. Na pierwszym wykresie widać, że po przepięciu sesji TCP na serwery znajdujące się w tym samym segmencie sieci liczba retransmisji drastycznie spadła. Pełny sukces jest widoczny na drugim grafie za sprawą migracji reszty serwerów. Wskutek tej operacji ilość zgub spadła z 61/sec do 4/sec przy średnim ruchu 11.3 Mbps.

Więcej informacji: Linux ftrace TCP Retransmit Tracing

Kategorie K a t e g o r i e : Administracja

Tagi T a g i : , , , , , , , ,

Podobne artykuły:

Komentowanie tego wpisu jest zablokowane.