Tenemos infraestructura distribuida en algunos lugares importantes de todo el mundo: Singapur, Londres y Los Ángeles. El RTT entre dos ubicaciones es superior a 150 ms.
Recientemente hemos actualizado todos los servidores para usar enlaces de 1Gbps (desde 100Mbps). Hemos estado ejecutando algunas pruebas basadas en TCP entre servidores en diferentes ubicaciones y hemos visto algunos resultados sorprendentes. Estos resultados son completamente repetibles.
- Los Ángeles (100Mbps) a Londres (100Mbps): rendimiento de ~ 96Mbps
- Los Ángeles (100Mbps) a Londres (1Gbps): rendimiento de ~ 96Mbps
- Los Ángeles (1 Gbps) a Londres (100 Mbps): rendimiento de 10-40 Mbps (volátil)
- Los Ángeles (1 Gbps) a Londres (1 Gbps): rendimiento de 10-40 Mbps (volátil)
- Los Ángeles (1 Gbps) a Los Ángeles (1 Gbps): rendimiento> 900 Mbps
Parece que cada vez que el remitente se ejecuta a 1 Gbps, nuestro rendimiento se ve muy afectado por los enlaces largos.
El enfoque de prueba anterior es extremadamente simple: solo estoy usando cURL para descargar un binario de 1 GB del servidor de destino (por lo tanto, en el caso anterior, el cliente cURL se ejecuta en el servidor de Londres y descarga desde LA, de modo que LA es el remitente) . Esto está usando una sola conexión TCP, por supuesto.
Repitiendo las mismas pruebas sobre UDP usando iperf, ¡el problema desaparece!
- Los Ángeles (100Mbps) a Londres (100Mbps): rendimiento de ~ 96Mbps
- Los Ángeles (100Mbps) a Londres (1Gbps): rendimiento de ~ 96Mbps
- Los Ángeles (1Gbps) a Londres (100Mbps): rendimiento de ~ 96Mbps
- Los Ángeles (1 Gbps) a Londres (1 Gbps): rendimiento> 250 Mbps
Esto apunta directamente a algún problema de configuración de TCP o NIC / puerto en mis ojos.
Ambos servidores ejecutan CentOS 6.x, con TCP cúbico. Ambos tienen ventanas de envío y recepción TCP máximas de 8 MB y tienen marcas de tiempo TCP y confirmaciones selectivas habilitadas. Se utiliza la misma configuración TCP en todos los casos de prueba. La configuración TCP completa está a continuación:
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
Se adjuntan un par de imágenes de gráficos IO Wirehark de algunos casos de prueba (lo siento, no puedo publicar imágenes directamente todavía):
Caso de prueba 1 (100Mbps -> 100Mbps) - transferencia suave y agradable. Sin pérdidas en la captura. - http://103.imagebam.com/download/dyNftIGh-1iCFbjfMFvBQw/25498/254976014/100m.png
Caso de prueba 3 (1 Gbps -> 100 Mbps) : la transferencia de votaile tarda mucho tiempo en alcanzar cualquier velocidad, nunca se acerca a 100 Mbps. ¡Sin embargo, no hay pérdidas / retransmisiones en la captura! - http://101.imagebam.com/download/KMYXHrLmN6l0Z4KbUYEZnA/25498/254976007/1g.png
En resumen, cuando se usa un enlace largo con una conexión de 1 Gbps, obtenemos un rendimiento TCP mucho menor que cuando usamos una conexión de 100 Mbps.
¡Apreciaría mucho algunos consejos de cualquier experto en TCP!
¡Gracias!
ACTUALIZACIÓN (2013-05-29):
Hemos resuelto el problema con el caso de prueba n. ° 4 anterior (remitente de 1 Gbps, receptor de 1 Gbps, en un RTT grande). Ahora podemos alcanzar ~ 970Mbps dentro de un par de segundos desde el inicio de la transferencia. El problema parece haber sido un cambio utilizado con el proveedor de alojamiento. Mudarse a uno diferente resolvió eso.
Sin embargo, el caso de prueba # 3 en su mayoría sigue siendo problemático. Si tenemos un receptor funcionando a 100Mbps y el emisor a 1Gbps, entonces vemos una espera de aproximadamente 2-3 minutos para que el receptor alcance los 100Mbps (pero ahora alcanza la velocidad completa, a diferencia de antes). Tan pronto como bajemos el emisor a 100Mbps o aumentemos el receptor a 1Gbps, el problema desaparecerá y podremos acelerar a toda velocidad en uno o dos segundos.
La razón subyacente es que estamos viendo pérdidas, por supuesto, muy pronto después de que comience la transferencia. Sin embargo, esto no concuerda con mi comprensión de cómo funciona el inicio lento; la velocidad de la interfaz no debería influir en esto, ya que debería regirse por los ACK del receptor.
Sugerencias recibidas con gratitud por favor! ¡Si pudiera ofrecer una recompensa aquí, lo haría!
tcp_*mem = 4096 1048576 33554432
No ha habilitado Jumbo Frames en los enlaces de 1 Gbps, ¿verdad? Eso podría estar causando fragmentación en alguna parte.