Dysponujemy infrastrukturą w kilku głównych lokalizacjach na całym świecie - Singapurze, Londynie i Los Angeles. RTT pomiędzy dowolnymi dwoma lokalizacjami wynosi ponad> 150ms.
Niedawno zaktualizowaliśmy wszystkie serwery, aby korzystały z łączy 1 Gb / s (od 100 Mb / s). Przeprowadziliśmy kilka testów opartych na TCP między serwerami w różnych lokalizacjach i uzyskaliśmy zaskakujące wyniki. Te wyniki są całkowicie powtarzalne.
- Od Los Angeles (100 Mb / s) do Londynu (100 Mb / s): przepustowość ~ 96 Mb / s
- Z Los Angeles (100 Mb / s) do Londynu (1 Gb / s): przepustowość ~ 96 Mb / s
- Od Los Angeles (1 Gb / s) do Londynu (100 Mb / s): przepustowość 10-40 Mb / s (lotna)
- Od Los Angeles (1 Gb / s) do Londynu (1 Gb / s): przepustowość 10-40 Mb / s (lotna)
- Od Los Angeles (1 Gb / s) do Los Angeles (1 Gb / s): przepustowość> 900 Mb / s
Wygląda na to, że ilekroć nadawca działa z prędkością 1 Gb / s, nasza przepustowość znacznie spada z powodu długich łączy.
Wcześniejsze podejście do testowania jest niezwykle proste - po prostu używam cURL, aby pobrać plik binarny 1 GB z serwera docelowego (więc w powyższym przypadku klient cURL działa na serwerze w Londynie i pobiera z LA, więc LA jest nadawcą) . Oczywiście używa to jednego połączenia TCP.
Powtarzając te same testy przez UDP przy użyciu iperf, problem znika!
- Od Los Angeles (100 Mb / s) do Londynu (100 Mb / s): przepustowość ~ 96 Mb / s
- Z Los Angeles (100 Mb / s) do Londynu (1 Gb / s): przepustowość ~ 96 Mb / s
- Od Los Angeles (1 Gb / s) do Londynu (100 Mb / s): przepustowość ~ 96 Mb / s
- Od Los Angeles (1 Gb / s) do Londynu (1 Gb / s): przepustowość> 250 Mb / s
Wskazuje to wprost na problem z konfiguracją TCP lub NIC / portu w moich oczach.
Na obu serwerach działa CentOS 6.x, z sześciennym TCP. Oba mają maksymalnie 8 MB okien wysyłania i odbierania TCP oraz włączone znaczniki czasu TCP i selektywne potwierdzenia. Ta sama konfiguracja TCP jest używana we wszystkich przypadkach testowych. Pełna konfiguracja TCP znajduje się poniżej:
net.core.somaxconn = 128
net.core.xfrm_aevent_etime = 10
net.core.xfrm_aevent_rseqth = 2
net.core.xfrm_larval_drop = 1
net.core.xfrm_acq_expires = 30
net.core.wmem_max = 8388608
net.core.rmem_max = 8388608
net.core.wmem_default = 131072
net.core.rmem_default = 131072
net.core.dev_weight = 64
net.core.netdev_max_backlog = 1000
net.core.message_cost = 5
net.core.message_burst = 10
net.core.optmem_max = 20480
net.core.rps_sock_flow_entries = 0
net.core.netdev_budget = 300
net.core.warnings = 1
net.ipv4.tcp_timestamps = 1
net.ipv4.tcp_window_scaling = 1
net.ipv4.tcp_sack = 1
net.ipv4.tcp_retrans_collapse = 1
net.ipv4.tcp_syn_retries = 5
net.ipv4.tcp_synack_retries = 5
net.ipv4.tcp_max_orphans = 262144
net.ipv4.tcp_max_tw_buckets = 262144
net.ipv4.tcp_keepalive_time = 7200
net.ipv4.tcp_keepalive_probes = 9
net.ipv4.tcp_keepalive_intvl = 75
net.ipv4.tcp_retries1 = 3
net.ipv4.tcp_retries2 = 15
net.ipv4.tcp_fin_timeout = 60
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_tw_recycle = 0
net.ipv4.tcp_abort_on_overflow = 0
net.ipv4.tcp_stdurg = 0
net.ipv4.tcp_rfc1337 = 0
net.ipv4.tcp_max_syn_backlog = 2048
net.ipv4.tcp_orphan_retries = 0
net.ipv4.tcp_fack = 1
net.ipv4.tcp_reordering = 3
net.ipv4.tcp_ecn = 2
net.ipv4.tcp_dsack = 1
net.ipv4.tcp_mem = 1528512 2038016 3057024
net.ipv4.tcp_wmem = 4096 131072 8388608
net.ipv4.tcp_rmem = 4096 131072 8388608
net.ipv4.tcp_app_win = 31
net.ipv4.tcp_adv_win_scale = 2
net.ipv4.tcp_tw_reuse = 0
net.ipv4.tcp_frto = 2
net.ipv4.tcp_frto_response = 0
net.ipv4.tcp_low_latency = 0
net.ipv4.tcp_no_metrics_save = 0
net.ipv4.tcp_moderate_rcvbuf = 1
net.ipv4.tcp_tso_win_divisor = 3
net.ipv4.tcp_congestion_control = cubic
net.ipv4.tcp_abc = 0
net.ipv4.tcp_mtu_probing = 0
net.ipv4.tcp_base_mss = 512
net.ipv4.tcp_workaround_signed_windows = 0
net.ipv4.tcp_dma_copybreak = 4096
net.ipv4.tcp_slow_start_after_idle = 1
net.ipv4.tcp_available_congestion_control = cubic reno
net.ipv4.tcp_allowed_congestion_control = cubic reno
net.ipv4.tcp_max_ssthresh = 0
net.ipv4.tcp_thin_linear_timeouts = 0
net.ipv4.tcp_thin_dupack = 0
W załączeniu jest kilka zdjęć grafów IO Wireshark niektórych przypadków testowych (przepraszam, nie mogę jeszcze publikować zdjęć bezpośrednio):
Przypadek testowy 1 (100 Mb / s -> 100 Mb / s) - niezły, płynny transfer. Brak strat w schwytaniu. - http://103.imagebam.com/download/dyNftIGh-1iCFbjfMFvBQw/25498/254976014/100m.png
Przypadek testowy 3 (1 Gb / s -> 100 Mb / s) - przesłanie głosu pocztą elektroniczną, osiągnięcie prędkości zajmuje dużo czasu - nigdy nie osiąga prędkości 100 Mb / s. Jeszcze żadnych strat / retransmisji podczas przechwytywania! - http://101.imagebam.com/download/KMYXHrLmN6l0Z4KbUYEZnA/25498/254976007/1g.png
Podsumowując, gdy używane jest długie łącze z połączeniem 1 Gb / s, uzyskujemy znacznie niższą przepustowość TCP niż w przypadku połączenia 100 Mb / s.
Byłbym bardzo wdzięczny za wskazówki od ekspertów TCP!
Dzięki!
AKTUALIZACJA (29.05.2013):
Rozwiązaliśmy problem z przypadkiem testowym nr 4 powyżej (nadawca 1 Gb / s, odbiornik 1 Gb / s, w dużym RTT). Możemy teraz osiągnąć ~ 970 Mb / s w ciągu kilku sekund od rozpoczęcia transferu. Wydaje się, że problem dotyczy przełącznika używanego przez dostawcę hostingu. Przejście do innego rozwiązało to.
Jednak przypadek testowy nr 3 w większości pozostaje problematyczny. Jeśli mamy odbiornik działający z prędkością 100 Mb / s, a nadawca z prędkością 1 Gb / s, to widzimy około 2-3 minut oczekiwania na osiągnięcie przez odbiornik 100 Mb / s (ale teraz osiąga pełną prędkość, inaczej niż wcześniej). Gdy tylko obniżymy nadawcę do 100 Mb / s lub zwiększymy odbiornik do 1 Gb / s, problem znika i możemy przyspieszyć do pełnej prędkości za sekundę lub dwie.
Głównym powodem jest to, że widzimy straty, oczywiście wkrótce po rozpoczęciu transferu. Nie oznacza to jednak, że rozumiem, jak działa powolny start; szybkość interfejsu nie powinna mieć na to żadnego wpływu, ponieważ powinna być regulowana przez potwierdzenia z odbiornika.
Proszę o sugestie z wdzięcznością! Gdybym mógł zaoferować nagrodę tutaj, zrobiłbym to!
źródło
tcp_*mem = 4096 1048576 33554432
Nie masz włączonych ramek Jumbo na łączach 1 Gb / s, prawda? To może gdzieś powodować fragmentację.Odpowiedzi:
Głównym problemem jest duże opóźnienie WAN. Będzie jeszcze gorzej, jeśli zginie także losowy pakiet.
1, tcp_mem również musi ustawić duży, aby przydzielić więcej pamięci. Na przykład ustaw go jako net.ipv4.tcp_mem = 4643328 6191104 9286656
2, możesz przechwytywać pakiety przez wireshark / tcpdump przez około kilka minut, a następnie analizować, czy utracił losowy pakiet. Możesz również przesłać plik pakietów, jeśli chcesz.
3, możesz spróbować dostroić inne parametry tcp np. ustaw tcp_westwood = 1 i tcp_bic = 1
źródło
Rozwiązany! Aby uzyskać szczegółowe informacje, patrz http://comments.gmane.org/gmane.linux.drivers.e1000.devel/11813
Krótko mówiąc, wygląda na to, że podłączony serwer 1 Gb / s wysyłałby gwałtowny ruch w fazie wykładniczej fazy wzrostu TCP, który zalałby bufory w niektórych urządzeniach pośrednich (kto wie co). Pozostawia to dwie opcje:
1) Skontaktuj się z każdym pośrednim operatorem sieci i poproś, aby skonfigurowali odpowiednie bufory, aby umożliwić moją pożądaną przepustowość i RTT. Całkiem mało prawdopodobne! 2) Ogranicz wybuchy.
Zdecydowałem się ograniczyć każdy przepływ TCP, aby działał co najwyżej 100 Mb / s. Liczba tutaj jest dość dowolna - wybrałem 100 Mb / s wyłącznie dlatego, że wiedziałem, że poprzednia ścieżka może obsłużyć 100 Mb / s i nie potrzebowałem już więcej dla pojedynczego przepływu .
Mam nadzieję, że to pomoże komuś w przyszłości.
źródło
Problem nie zniknął, ostrożnie 75% twoich pakietów jest upuszczanych? Jeśli TCP cały czas przechodzi w wolne uruchamianie, średnia przepustowość może być raczej niska.
Przy okazji, czy macie wzorce dla Londynu do LA i Londynu do Londynu?
źródło