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!
fuente
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.Respuestas:
El problema principal es el gran retraso de WAN. Será mucho peor si también se pierde un paquete aleatorio.
1, tcp_mem también necesita establecer grande para asignar más memoria. Por ejemplo, configúrelo como net.ipv4.tcp_mem = 4643328 6191104 9286656
2, puede capturar los paquetes a través de wireshark / tcpdump durante unos minutos y luego analizar si se ha perdido un paquete aleatorio. También puede cargar el archivo de paquetes si lo desea.
3, puede intentar ajustar los otros parámetros tcp Ej. establecer tcp_westwood = 1 y tcp_bic = 1
fuente
Resuelto! Para más detalles ver http://comments.gmane.org/gmane.linux.drivers.e1000.devel/11813
En resumen, parece que el servidor conectado de 1 Gbps enviaría ráfagas de tráfico durante la fase de crecimiento exponencial de TCP que inundaría las memorias intermedias en algún dispositivo intermedio (quién sabe qué). Esto deja dos opciones:
1) Póngase en contacto con cada operador de red intermedio y pídales que configuren las memorias intermedias apropiadas para permitir mi ancho de banda y RTT deseados. ¡Muy poco probable! 2) Limite las explosiones.
Elegí limitar cada flujo TCP para operar a 100Mbps como máximo. El número aquí es bastante arbitrario: elegí 100Mbps simplemente porque sabía que la ruta anterior podía manejar 100Mbps y no necesitaba más para un flujo individual .
Espero que esto ayude a alguien en el futuro.
fuente
El problema no parece haber desaparecido, ¿se descarta el 75% de sus paquetes? Si TCP entra en un inicio lento todo el tiempo, su ancho de banda promedio podría ser bastante bajo.
Por cierto, ¿tienes puntos de referencia para Londres a LA, y Londres a Londres?
fuente