Interaktywna powłoka przez tunel zastyga na kilka sekund, gdy trwa kopiowanie pliku, po czym wraca do pracy, jakby nic się nie stało. Problem ma tylko pobieranie, ale powłoka też czeka, a oba wracają w tym samym momencie. Ten wzorzec jest sygnaturą jednego niezawodnego strumienia niosącego wiele rozmów i przeżywa prawie każdą zmianę strojenia, którą ludzie próbują najpierw.

Warto czytać ten objaw uważnie, bo wskazuje na mechanizm, a nie na ustawienie: pauza jest wspólna, więc przyczyna jest wspólna, a wspólnym obiektem jest połączenie zewnętrzne. Wszystko inne w dzienniku wygląda wtedy normalnie.

Objaw: wszystko zatrzymuje się naraz

Dwa wewnętrzne połączenia zacinające się razem to wskazówka. Wolne pobieranie i wolna powłoka to odrębne rozmowy TCP z odrębnymi numerami sekwencji i odrębnym stanem przeciążenia, więc awaria w jednej nie powinna dotykać drugiej. Gdy zatrzymują się równocześnie, coś nad nimi porządkuje ich bajty.

Tym czymś jest transport tunelu. W trybie TCP OpenVPN zapisuje enkapsulowane pakiety do jednego połączenia TCP z drugim końcem, a umowa TCP to dostarczanie w kolejności pojedynczego strumienia bajtów. Późniejsze bajty nie są przekazywane aplikacji przed brakującymi, niezależnie od tego, do której wewnętrznej rozmowy należą.

Zwróć uwagę, czego objaw nie mówi. Nie mówi, że ścieżka jest zepsuta, że serwer jest przeciążony albo że szyfr jest wolny. Te dają inne kształty: równomiernie niską przepustowość, przekroczenia czasu lub awarie dotykające jednego kierunku. Wspólna pauza, która kończy się po ponownym przesłaniu utraconego segmentu, jest konkretnie efektem uporządkowania.

Jeden zewnętrzny strumień bajtów, wiele wewnętrznych rozmów

Wyobraź sobie tunel niosący jednocześnie pobieranie i powłokę. Jeden segment połączenia zewnętrznego ginie. Kolejne segmenty mogą dotrzeć do hosta odbiorczego, a odbierający stos TCP je potwierdzi, ale nie może przekazać ich w górę, dopóki luka nie zostanie wypełniona. OpenVPN nie ma więc czego czytać dla powłoki, choć bajty samej powłoki dotarły dawno temu.

To blokada na początku kolejki wewnątrz jednego połączenia i nie wymaga, by obie aplikacje dzieliły wewnętrzne połączenie. Dzielą zewnętrzne i to wystarcza.

Efekt drugiego rzędu pogarsza sprawę. Wewnętrzny nadawca, który nie widzi potwierdzeń, może ponownie przesłać dane, które warstwa zewnętrzna już próbuje dostarczyć. Ta retransmisja staje się dodatkowym ruchem tunelu na ścieżce, która właśnie dowiodła, że potrafi gubić segmenty, więc praca nad odzyskiwaniem konkuruje z odzyskiwaniem, które ma znaczenie.

Nic z tego nie gwarantuje załamania. Na czystej ścieżce z krótkimi rundami i hojnymi kolejkami taki układ może być całkiem użyteczny przez lata. Awaria pojawia się, gdy utrata, opóźnienie i głębokość kolejki zbiegają się razem, dlatego raporty skupiają się wokół przeciążonych łączy wysyłkowych i łączy mobilnych, a nie dobrze zaopatrzonych biur.

Dlaczego dłuższy wewnętrzny licznik nie może pomóc

Podniesienie minimalnego limitu czasu retransmisji na trasie za pomocą rto_min odwleka retransmisję opartą na liczniku dla lokalnie generowanego ruchu TCP korzystającego z tej trasy. To prawdziwe pokrętło z prawdziwym efektem i dotyczy problemu drugiego rzędu, a nie pierwszego.

ip route show
ip route show cache 2>/dev/null | head
ss -tin dst 10.70.0.1

Czego nie potrafi: uwolnić zewnętrznych bajtów poza kolejnością, odzyskać brakującego segmentu szybciej ani sprawić, by zdalny serwer aplikacji przyjął ten sam licznik. Odbierający stos nadal dostarcza w kolejności, a nadawca na drugim końcu nadal używa własnych pomiarów czasu rundy.

Nie wyłącza też wszystkich innych mechanizmów odzyskiwania po utracie. Tam, gdzie prawdziwa utrata wymaga odzyskiwania opartego na liczniku, większe minimum każe aplikacji czekać dłużej przed działaniem, co jest przeciwieństwem tego, czego potrzebuje sesja wrażliwa na opóźnienia.

Stała dolna granica dwunastu sekund pojawia się w poradach na ten temat, jakby istnienie tunelu TCP ją implikowało. Licznik retransmisji opisany w RFC 6298 wywodzi się z mierzonego czasu rundy z wykładniczym wycofywaniem, więc stała granica jest wyborem polityki dla konkretnej ścieżki, a nie wymogiem protokołu. Zastosowana szeroko ukrywa objaw, zmieniając jednocześnie odzyskiwanie dla każdego przepływu objętego tą trasą.

Co robi, a czego nie robi tcp-nodelay

Opcja tunelu wyłączająca buforowanie w stylu Nagle'a na gnieździe transportowym ma wąski cel: powstrzymuje małe zapisy przed czekaniem na więcej danych przed wysłaniem. To pomaga ruchowi interaktywnemu uniknąć dodatkowego opóźnienia na skądinąd zdrowej ścieżce.

Nie czyni transportu nieuporządkowanym i nie skraca odzyskiwania po utraconym segmencie. Powłoka, która zatrzymuje się na limit czasu retransmisji, zatrzyma się także z tą opcją włączoną, bo opcja nigdy nie dotknęła reguły uporządkowania.

Pomylić jedno z drugim łatwo, bo oba opisuje się jako poprawki opóźnienia. Jedna usuwa sztuczne oczekiwanie wprowadzone przez buforowanie, druga wymagałaby zmiany tego, co gwarantuje transport, a żadna opcja gniazda tego nie robi.

Jak uczciwie porównywać transporty

Jeśli operator na to pozwala i oba serwisy istnieją, porównaj usługę UDP i usługę TCP niosące to samo obciążenie po tej samej ścieżce dostępu do tego samego serwera. Zmiana kraju, dostawcy lub generacji serwera między dwoma testami wprowadza zmienną, która zdominuje wynik.

Wypatruj wspólnej pauzy, a nie liczby przepustowości. Kilka wewnętrznych aplikacji zacinających się razem podczas zewnętrznej utraty to obserwacja, która identyfikuje blokadę na początku kolejki; jedna niższa liczba z testu prędkości tego nie robi.

Autoryzowane przechwyty na interfejsie tunelu i na interfejsie fizycznym czysto rozdzielają obie warstwy, bo wewnętrzne i zewnętrzne retransmisje należą do różnych połączeń o różnych przestrzeniach sekwencji. Widok wewnętrznych retransmisji, gdy strumień zewnętrzny pokazuje lukę, jest bezpośrednim dowodem.

Przejście na UDP usuwa dodatkowy niezawodny strumień i zostawia wewnętrznemu TCP własne odzyskiwanie. Nie obiecuje zerowej utraty ani niskiego opóźnienia, a wysycone łącze, zbyt duże kolejki czy problem z MTU nadal będą wymagały naprawy. Ruch poza tunelem nigdy nie jest trzymany za luką sekwencji tunelu, choć nadal może cierpieć, gdy obie ścieżki dzielą jedno przeciążone łącze, a to wspólne wąskie gardło zasługuje na własne dochodzenie, zamiast być wliczane w to.

Powiązane artykuły