Velocità effettiva TCP inferiore dal server 1 Gbps rispetto al server 100 Mbps su RTT di grandi dimensioni


9

Abbiamo infrastrutture distribuite in alcune delle principali località del mondo: Singapore, Londra e Los Angeles. La RTT tra due posizioni qualsiasi è superiore a> 150 ms.

Di recente abbiamo aggiornato tutti i server per utilizzare collegamenti da 1 Gbps (da 100 Mbps). Abbiamo eseguito alcuni test basati su TCP tra server in diverse posizioni e abbiamo riscontrato risultati sorprendenti. Questi risultati sono completamente ripetibili.

  1. Da Los Angeles (100 Mbps) a Londra (100 Mbps): velocità effettiva di ~ 96 Mbps
  2. Da Los Angeles (100 Mbps) a Londra (1 Gbps): velocità effettiva di ~ 96 Mbps
  3. Da Los Angeles (1 Gbps) a Londra (100 Mbps): throughput 10-40 Mbps (volatile)
  4. Da Los Angeles (1 Gbps) a Londra (1 Gbps): throughput 10-40 Mbps (volatile)
  5. Da Los Angeles (1 Gbps) a Los Angeles (1 Gbps):> 900 Mbps di throughput

Sembra che ogni volta che il mittente è in esecuzione a 1 Gbps, il nostro throughput soffre in modo molto significativo su collegamenti lunghi.

L'approccio di test precedente è estremamente semplice: sto solo usando cURL per scaricare un file binario da 1 GB dal server di destinazione (quindi nel caso sopra, il client cURL viene eseguito sul server di Londra e viene scaricato da LA, in modo che LA sia il mittente) . Questo ovviamente utilizza una singola connessione TCP.

Ripetendo gli stessi test su UDP usando iperf, il problema scompare!

  1. Da Los Angeles (100 Mbps) a Londra (100 Mbps): velocità effettiva di ~ 96 Mbps
  2. Da Los Angeles (100 Mbps) a Londra (1 Gbps): velocità effettiva di ~ 96 Mbps
  3. Da Los Angeles (1 Gbps) a Londra (100 Mbps): velocità effettiva di ~ 96 Mbps
  4. Da Los Angeles (1 Gbps) a Londra (1 Gbps): velocità effettiva> 250 Mbps

Ciò indica chiaramente alcuni problemi di configurazione TCP o NIC / porta ai miei occhi.

Entrambi i server eseguono CentOS 6.x, con TCP cubico. Entrambi hanno un massimo di 8 MB di finestre di invio e ricezione TCP e hanno timestamp TCP e riconoscimenti selettivi abilitati. La stessa configurazione TCP viene utilizzata in tutti i casi di test. La configurazione TCP completa è di seguito:

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

In allegato un paio di immagini dei grafici IO di WireShark di alcuni casi di test (scusate, non riesco ancora a pubblicare le immagini direttamente):

Caso di prova 1 (100 Mbps -> 100 Mbps) - trasferimento gradevole. Nessuna perdita di cattura. - http://103.imagebam.com/download/dyNftIGh-1iCFbjfMFvBQw/25498/254976014/100m.png

Test case 3 (1Gbps -> 100 Mbps) - trasferimento votaile, impiega molto tempo per raggiungere qualsiasi velocità - non si avvicina mai a 100 Mbps. Eppure nessuna perdita / ritrasmissione nella cattura! - http://101.imagebam.com/download/KMYXHrLmN6l0Z4KbUYEZnA/25498/254976007/1g.png

Quindi, in sintesi, quando viene utilizzato un collegamento lungo con una connessione da 1 Gbps, otteniamo un throughput TCP molto inferiore rispetto a quando utilizziamo una connessione da 100 Mbps.

Apprezzerei molto alcuni suggerimenti di tutti gli esperti TCP là fuori!

Grazie!

AGGIORNAMENTO (29/05/2013):

Abbiamo risolto il problema con il test case n. 4 sopra (mittente 1 Gbps, ricevitore 1 Gbps, su un RTT di grandi dimensioni). Ora possiamo raggiungere ~ 970 Mbps entro un paio di secondi dall'inizio del trasferimento. Il problema sembra essere stato uno switch utilizzato con il provider di hosting. Passare a un altro risolto questo.

Tuttavia, il caso di test n. 3 rimane per lo più problematico. Se abbiamo un ricevitore in esecuzione a 100 Mbps e il mittente a 1 Gbps, vediamo circa 2-3 minuti di attesa affinché il ricevitore raggiunga 100 Mbps (ma ora raggiunge la velocità massima, a differenza di prima). Non appena abbassiamo il mittente a 100 Mbps o aumentiamo il ricevitore a 1 Gbps, il problema scompare e possiamo accelerare alla massima velocità in uno o due secondi.

La ragione di fondo è che stiamo assistendo a perdite, ovviamente, molto presto dopo l'inizio del trasferimento. Tuttavia, ciò non coincide con la mia comprensione di come funziona l'avvio lento; la velocità dell'interfaccia non dovrebbe influire su ciò, poiché dovrebbe essere regolata dagli ACK del ricevitore.

Suggerimenti ricevuti con gratitudine per favore! Se potessi offrire una taglia qui, lo farei!


1
Stai utilizzando TCP offload sulla scheda NIC su entrambi i lati? Il tuo utilizzo dell'offload TCP varia da 100M a 1G NIC? Se questo è in uso in uno dei casi di test, potrebbe valere la pena ripetere i test con quello disabilitato solo per vedere se il motore di offload TCP sulla scheda di rete 100M potrebbe interferire con le prestazioni della comunicazione 1G (questo commento è intenzionalmente mano ondulata solo per far apparire TOE)
FliesLikeABrick

Buona domanda! L'offload della segmentazione TCP è disabilitato su entrambe le estremità. L'offload della segmentazione generica è abilitato su entrambe le estremità. L'ho anche ripetuto con TSO abilitato e non ha fatto alcuna differenza evidente.
Sam,

Prova a disabilitare l'offload della segmentazione generica, almeno sul lato 100M, e ripeti i test
FliesLikeABrick

Grazie per il suggerimento, ma nessuna gioia - stessi risultati con gso acceso o spento su entrambi i lati.
Sam,

1 Gbps a 150 ms + offre un prodotto di ritardo della larghezza di banda molto grande, oltre 18 Mb. Cosa succede se si aumentano i buffer del socket? tcp_*mem = 4096 1048576 33554432Non hai abilitato Jumbo Frames sui link 1Gbps, vero? Ciò potrebbe causare la frammentazione ambientale da qualche parte.
suprjami,

Risposte:


1

Il problema principale è il grande ritardo WAN. Sarà molto peggio se perdesse anche un pacchetto casuale.

1, anche tcp_mem deve essere impostato su grande per allocare più memoria. Ad esempio, impostarlo come net.ipv4.tcp_mem = 4643328 6191104 9286656

2, è possibile acquisire i pacchetti tramite WireShark / tcpdump per circa alcuni minuti, quindi analizzare se ha perso un pacchetto casuale. Puoi anche caricare il file dei pacchetti, se lo desideri.

3, puoi provare a sintonizzare gli altri parametri tcp Ad es. impostare tcp_westwood = 1 e tcp_bic = 1


Grazie, ma abbiamo provato tutti quelli. Il ritardo WAN non è il problema: possiamo usare quasi immediatamente 100 Mbps se utilizziamo porte da 100 Mbps, ma non appena si passa a 1 Gbps, allora siamo in toast.
Sam,

1

Risolto! Per i dettagli completi consultare http://comments.gmane.org/gmane.linux.drivers.e1000.devel/11813

In breve, sembra che il server connesso da 1 Gbps invierebbe scoppi di traffico durante la fase di crescita esponenziale di TCP che invaderebbe i buffer in alcuni dispositivi intermedi (chissà cosa). Questo lascia due opzioni:

1) Contatta ogni operatore di rete intermedio e fagli configurare i buffer appropriati per consentire la larghezza di banda e RTT desiderati. Abbastanza improbabile! 2) Limitare le esplosioni.

Ho scelto di limitare ogni flusso TCP per operare al massimo a 100 Mbps. Il numero qui è abbastanza arbitrario: ho scelto 100 Mbps solo perché sapevo che il percorso precedente poteva gestire 100 Mbps e non avevo più bisogno di un singolo flusso .

Spero che questo aiuti qualcuno in futuro.


0

Ripetendo gli stessi test su UDP usando iperf, il problema scompare!

Da Los Angeles (1 Gbps) a Londra (1 Gbps): velocità effettiva> 250 Mbps

Il problema non sembra essere scomparso, circa il 75% dei pacchetti vengono eliminati? Se TCP inizia sempre lentamente, la tua banda media potrebbe essere piuttosto bassa.

A proposito, hai dei benchmark per Londra a Los Angeles, e da Londra a Londra?


Ho dimenticato di dire che il client è lento ... Se ripetiamo con due client veloci, allora abbiamo raggiunto ~ 970 Mbps in senso bidirezionale.
Sam,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.