Transport

Kontrola Przeciążenia TCP

Algorytmy slow start, unikanie przeciążenia i szybkie odzyskiwanie.

Kontrola Przeciążenia TCP: Zakres i Cel

TCP współdzieli łącza i zasoby urządzeń przekazujących dane z innymi przepływami. Podczas pobierania pliku z serwera w Berlinie do hosta w Warszawie segmenty przechodzą przez kilka łączy i routerów. Dostępna przepustowość, kolejkowanie i czas obiegu mogą zmieniać się w trakcie transmisji, także między spokojnym okresem, takim jak godzina 3 nad ranem, a okresem dużego obciążenia.

Gdy natężenie ruchu przekracza pojemność łącza, w routerach rosną kolejki. obsługujące ruch na przeciążonej ścieżce mogą stać się wąskimi gardłami. Pełna kolejka zwiększa opóźnienie i może spowodować odrzucanie przychodzących pakietów. Ten stan to przeciążenie sieci (ang. network congestion).

Opóźnienie kolejkowania rośnie, gdy napływ danych przez dłuższy czas przekracza szybkość obsługi łącza, natomiast opóźnienie propagacji zależy głównie od długości trasy i medium. TCP nie mierzy bezpośrednio kolejki routera, dlatego nadawca wykorzystuje potwierdzenia jako zegar ACK i zmienia okno wysyłania na podstawie obserwowanego sprzężenia zwrotnego.

TCP potrzebuje zatem dwóch odrębnych ograniczeń. Kontrola Przepływu wykorzystuje okno ogłaszane przez odbiorcę, aby ilość danych nie przekroczyła dostępnego bufora. Kontrola Przeciążenia wykorzystuje okno przeciążeniowe nadawcy oraz sygnały z sieci, aby ograniczyć ruch wprowadzany do współdzielonej ścieżki. Mechanizmy chronią różne zasoby.

Jak TCP Wnioskuje o Przeciążeniu

TCP może otrzymać jawny sygnał przez ECN (Jawne Powiadamianie o Przeciążeniu), lecz klasyczne mechanizmy kontroli przeciążenia wnioskują o stanie ścieżki z potwierdzeń, liczników retransmisji i strat. Nadawca obserwuje te zdarzenia, zamiast odczytywać stan poszczególnych routerów.

ECN pozwala urządzeniu sieciowemu oznaczyć pakiety zamiast je odrzucać, gdy przeciążenie zaczyna narastać, pod warunkiem wcześniejszego uzgodnienia ECN przez punkty końcowe. Odbiorca odzwierciedla oznaczenie w potwierdzeniach, a nadawca ogranicza szybkość wysyłania zgodnie z używanym algorytmem kontroli przeciążenia.

Jednym z głównych sygnałów opartych na stratach jest utrata pakietu. Przepełnienie kolejki jest częstą przyczyną, lecz straty i opóźnienia mogą mieć także inne przyczyny, więc sygnał wskazuje na przeciążenie, lecz go nie dowodzi. TCP ma dwa główne sposoby wykrywania możliwej utraty pakietu:

  • Przekroczenie Limitu Czasu Retransmisji (RTO)

    Nadawca TCP zwykle utrzymuje jeden licznik retransmisji dla najwcześniejszego niepotwierdzonego segmentu. Oczekuje, że otrzyma potwierdzenie (ACK) od odbiorcy, zanim ten licznik wygaśnie. Po jego wygaśnięciu TCP traktuje segment jako utracony albo nadmiernie opóźniony. Jest to sygnał poważnego przeciążenia, ponieważ do nadawcy nie dotarło potwierdzenie w wymaganym czasie.

  • Trzy Zduplikowane Potwierdzenia ACK

    Jest to szybsza heurystyka. Załóżmy, że nadawca wysyła segmenty 1, 2, 3, 4 i 5, segment 3 ginie, a segmenty 4 i 5 docierają. Odbiorca wysyła zduplikowane skumulowane ACK dla końca segmentu 2. Po trzech zduplikowanych ACK nadawca wnioskuje, że kolejny segment zaginął, i retransmituje go bez oczekiwania na RTO. Zmiana kolejności lub powielenie pakietów także może powodować zduplikowane ACK, więc ten sygnał nie potwierdza utraty.

Zmienne Kontroli Przeciążenia

Aby zaimplementować swoją strategię kontroli przeciążenia, TCP utrzymuje po stronie nadawcy dwie krytyczne zmienne stanu dla każdego połączenia.

  • Okno Przeciążeniowe (cwnd)

    'cwnd' to limit nadawcy dotyczący liczby bajtów w drodze, czyli wysłanych i jeszcze niepotwierdzonych. TCP dostosowuje tę wartość na podstawie sygnałów przeciążenia. Współpracuje ona z oknem ogłaszanym przez odbiorcę ('rwnd'). Liczba bajtów, które nadawca może przesłać, jest równa minimumz 'cwnd' i 'rwnd'. Pozwala to uwzględnić stan ścieżki oraz pojemność odbiorcy.

    FlightSize oznacza ilość danych pozostających w drodze w chwili zdarzenia przeciążeniowego. Może być mniejszy od okna przeciążeniowego, gdy transmisję ogranicza aplikacja albo odbiorca, dlatego obliczenie progu z użyciem FlightSize nie zakłada wysłania całego okna.

  • Próg Powolnego Startu (ssthresh)

    'ssthresh' to zmienna wybierająca fazę Powolnego Startu albo bardziej zachowawczego Unikania Przeciążenia. Początkowo może mieć dużą wartość. Po wykryciu straty nadawca stosujący regułę RFC 5681 ustawia ją na większą z wartości: połowę rozmiaru FlightSize oraz 2 SMSS. Dokładna reakcja zależy od sygnału straty i algorytmu kontroli przeciążenia.

    Gdy 'cwnd' jest mniejsze od 'ssthresh', nadawca w stylu Reno używa Powolnego Startu. Przy wartości równej progowi albo większej przechodzi do Unikania Przeciążenia, więc próg zmienia regułę wzrostu i nie oznacza zmierzonej przepustowości łącza.

Faza 1: Powolny Start (Slow Start) - W Poszukiwaniu Przepustowości

Na początku połączenia TCP nadawca ma ograniczoną wiedzę o pojemności ścieżki. Może to być szybkie łącze światłowodowe albo wolne łącze satelitarne. Natychmiastowa duża seria danych mogłaby wywołać przeciążenie, natomiast zbyt ostrożne wysyłanie nie wykorzystałoby szybkiej ścieżki. TCP używa algorytmu Powolnego Startu, aby ją zbadać.

Wzrost w tej fazie może być w przybliżeniu wykładniczy, gdy każde potwierdzenie zwiększa okno. Nazwa odnosi się do rozpoczęcia od ograniczonego okna zamiast od natychmiastowego wysłania pełnej oszacowanej pojemności ścieżki.

Nowo potwierdzone dane napędzają zegar ACK. Gdy potwierdzenia przychodzą seriami, implementacja nadal musi respektować limit okna przeciążeniowego i może stosować zliczanie bajtów albo ograniczenia związane z opóźnionymi ACK, aby uniknąć nadmiernego wzrostu wywołanego taką serią.

Mechanizm Powolnego Startu

  1. Połączenie rozpoczyna się z początkowym Oknem Przeciążeniowym ('cwnd'). Eksperymentalny RFC 6928 dopuszcza górne ograniczenie min⁡(10 MSS,max⁡(2 MSS,14600 B))\min(10\,\text{MSS},\max(2\,\text{MSS},14600\,\text{B})), lecz implementacja może wybrać mniejszą wartość. Limit wyraża się w .
  2. Za każde potwierdzenie (ACK) nowych danych nadawca zwiększa 'cwnd' najwyżej o jeden SMSS. Algorytmy zliczające bajty mogą uwzględniać liczbę nowo potwierdzonych bajtów.
  3. Ponieważ nadawca może wysłać wiele segmentów w jednym obiegu, może otrzymać wiele potwierdzeń w odpowiedzi. W efekcie 'cwnd' w przybliżeniu podwaja się co Czas Obiegu (RTT).

SMSS oznacza użyteczny rozmiar segmentu nadawcy, natomiast MSS jest wartością ogłaszaną przez partnera. Rzeczywisty wzrost ogranicza też ilość nowo potwierdzonych danych oraz okno odbiorcy, dlatego opis podwajania jest przybliżeniem dla nadawcy mającego stale dane do wysłania.

Ten wzrost pozwala TCP oszacować dostępną pojemność ścieżki. Powolny Start trwa, dopóki 'cwnd' nie osiągnie 'ssthresh' albo nie zostanie wykryte przeciążenie. Po osiągnięciu progu nadawca zgodny z wariantem Reno przechodzi do Unikania Przeciążenia.

Faza 2: Unikanie Przeciążenia (Congestion Avoidance) - Delikatne Sondowanie

Po Powolnym Starcie nadawca TCP zgodny z wariantem Reno wchodzi w bardziej zachowawczą fazę Unikania Przeciążenia. Bada dodatkową pojemność przez kontrolowany wzrost zamiast wcześniejszego wzrostu wykładniczego.

To zachowanie należy do strategii Dodatkowego Wzrostu, Mnożeniowego Spadku (AIMD). Unikanie Przeciążenia jest częścią dodatkowego wzrostu w wariancie Reno.

Mechanizm Unikania Przeciążenia

Zamiast podwajać 'cwnd' co RTT nadawca zwiększa je w sposób liniowy, addytywny. Celem podstawowego algorytmu jest wzrost o około 1 SMSS na RTT.

Przyrost dla pojedynczego ACK staje się mniejszy wraz ze wzrostem 'cwnd'. Zsumowanie przyrostów dla mniej więcej jednego okna potwierdzeń daje docelowo jeden segment na RTT, w rezultacie zasada pozostaje niezależna od liczby ACK użytych do dostarczenia tego okna.

Osiąga się to przez zwiększanie 'cwnd' o mały ułamek za każdy ACK. Podstawowe przybliżenie ma postać cwnd=cwnd+SMSS×(SMSS/cwnd)\text{cwnd} = \text{cwnd} + \text{SMSS} \times (\text{SMSS} / \text{cwnd}) dla każdego ACK. Po potwierdzeniu jednego okna całkowity wzrost wynosi około 1 SMSS. Połączenie pozostaje w Unikaniu Przeciążenia do wykrycia straty albo jawnego sygnału przeciążenia.

Reakcja na Przeciążenie: Mnożeniowy Spadek

Część AIMD określana jako mnożeniowy spadek opisuje redukcję po wykryciu przeciążenia. Reakcja zależy od tego, czy strata została wykryta przez RTO, zduplikowane ACK, ECN albo inny algorytm odzyskiwania.

Reakcja na Timeout (RTO)

Przekroczenie Limitu Czasu Retransmisji jest traktowane jako sygnał poważnego przeciążenia. Podstawowa reakcja RFC 5681 obejmuje:

  1. 'ssthresh' jest ustawiany na większą z wartości: połowę FlightSize oraz 2 SMSS, przy pierwszym przekroczeniu limitu czasu dla tego segmentu.
  2. 'cwnd' jest resetowany do małej wartości początkowej (np. 1 SMSS).
  3. Połączenie ponownie wchodzi w fazę Powolnego Startu.

Ustawienie 'cwnd' na okno utraty zmniejsza ruch nadawcy, zanim Powolny Start ponownie zbada ścieżkę.

Timeout uruchamia także ponownie licznik retransmisji dla retransmitowanych danych. Powtarzające się przekroczenia limitu utrzymują zachowawczą szybkość wysyłania do chwili, gdy potwierdzenia dostarczą dowodu, że ścieżka może przenieść większy ruch.

Reakcja na Trzy Zduplikowane ACK: Szybka Retransmisja i Szybkie Odzyskiwanie

Trzy zduplikowane ACK wskazują prawdopodobną lukę, gdy kolejne segmenty nadal docierają do odbiorcy. Zmiana kolejności może wywołać ten sam sygnał, lecz nadawca używa go do uruchomienia Szybkiej Retransmisji i Szybkiego Odzyskiwania bez oczekiwania na RTO.

Próg zduplikowanych potwierdzeń oznacza trzy ACK po pierwszym skumulowanym ACK dla tego samego zakresu numerów. Selektywne potwierdzanie może wskazać dodatkowe odebrane zakresy, natomiast klasyczny Reno opiera się na potwierdzeniach skumulowanych i ma mniej informacji o wielu stratach.

  1. Szybka Retransmisja: Po otrzymaniu trzeciego zduplikowanego ACK nadawca retransmituje segment wskazany przez skumulowane potwierdzenie, bez oczekiwania na licznik RTO.
  2. Szybkie Odzyskiwanie:Zamiast resetować 'cwnd' do 1, TCP wykonuje mnożeniowy spadek:
    • 'ssthresh' jest ustawiany na większą z wartości: połowę FlightSize oraz 2 SMSS.
    • W klasycznym Reno 'cwnd' jest tymczasowo ustawiane na 'ssthresh' powiększone o 3 SMSS, ponieważ trzy zduplikowane ACK wskazują dane, które opuściły sieć.
    Następnie TCP bezpośrednio wchodzi w fazę Unikania Przeciążenia, kontynuując swój liniowy wzrost od tego nowego, niższego punktu startowego.

Klasyczny Reno po odzyskaniu zmniejsza 'cwnd' do 'ssthresh' i kontynuuje Unikanie Przeciążenia. NewReno modyfikuje odzyskiwanie po wielu stratach, reagując na częściowe potwierdzenia.

Ewolucja Kontroli Przeciążenia

Klasyczne połączenie Powolnego Startu, Unikania Przeciążenia i Szybkiego Odzyskiwania w Reno pozostaje modelem odniesienia dla kontroli przeciążenia TCP. Szybsze i dłuższe ścieżki, określane także jako Long Fat Networks (LFNs), o dużym iloczynie przepustowości i opóźnienia ujawniły wolniejsze odzyskiwanie, co doprowadziło do algorytmów z innymi funkcjami wzrostu.

Iloczyn przepustowości i opóźnienia ma szczególne znaczenie na długich ścieżkach. Nadawca może potrzebować dużego okna danych w drodze, aby osiągnąć dostępną szybkość, podczas gdy algorytm oparty na stratach może zapełnić kolejki przed otrzymaniem sygnału straty. Nowsze algorytmy zmieniają zmienną sterującą albo funkcję wzrostu okna, aby uwzględnić tę zależność.

  • TCP NewReno

    NewReno rozszerza szybkie odzyskiwanie Reno dla połączeń, które nie mogą używać selektywnego potwierdzania TCP. Wykorzystuje częściowe potwierdzenia do wnioskowania o kolejnych stratach w tym samym oknie i retransmisji bez opuszczania odzyskiwania po pierwszym brakującym segmencie.

  • CUBIC

    CUBIC jest algorytmem kontroli przeciążenia TCP opisanym w standardzie i wykorzystuje sześcienną funkcję wzrostu okna zamiast liniowego wzrostu Reno. RFC 9438 wskazuje jego wdrożenie jako domyślne w stosach Linux, Windows i Apple. Fazy wklęsła i wypukła poprawiają skalowalność oraz stabilność szybkich, odległych ścieżek przy zachowaniu zachowania przyjaznego dla Reno.

    CUBIC wykorzystuje czas od ostatniego zdarzenia przeciążeniowego w funkcji okna, co zmniejsza zależność od szybkości ACK. Standard nadal wymaga reakcji na sygnały przeciążenia oraz współistnienia z ruchem w stylu Reno.

  • BBR (Bottleneck Bandwidth and Round-trip propagation time)

    BBR, pierwotnie opracowany przez Google, stosuje podejście oparte na modelu. Mierzy tempo dostarczania i czas obiegu oraz może uwzględniać sygnały strat lub ECN zależnie od wersji algorytmu, a następnie steruje szybkością wysyłania oraz ilością danych w drodze. Jego cele obejmują dużą przepustowość przy mniejszym kolejkowaniu niż w algorytmie opartym wyłącznie na stratach, z ograniczeniem wzrostu kolejek określanego jako bufferbloat. Aktualny opis IETF ma status eksperymentalnego Internet-Draft i nie jest opublikowanym RFC.

    BBR oddziela estymację przepustowości wąskiego gardła od estymacji opóźnienia propagacji i okresowo sonduje oba parametry. Szczegóły zależą od implementacji oraz wersji opisu, dlatego BBR nie powinien być przedstawiany jako domyślne zachowanie każdego stosu TCP.

Powiązane artykuły