Rendimiento TCP más bajo del servidor de 1 Gbps que el servidor de 100 Mbps sobre RTT grande

9

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.

  1. Los Ángeles (100Mbps) a Londres (100Mbps): rendimiento de ~ 96Mbps
  2. Los Ángeles (100Mbps) a Londres (1Gbps): rendimiento de ~ 96Mbps
  3. Los Ángeles (1 Gbps) a Londres (100 Mbps): rendimiento de 10-40 Mbps (volátil)
  4. Los Ángeles (1 Gbps) a Londres (1 Gbps): rendimiento de 10-40 Mbps (volátil)
  5. 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!

  1. Los Ángeles (100Mbps) a Londres (100Mbps): rendimiento de ~ 96Mbps
  2. Los Ángeles (100Mbps) a Londres (1Gbps): rendimiento de ~ 96Mbps
  3. Los Ángeles (1Gbps) a Londres (100Mbps): rendimiento de ~ 96Mbps
  4. 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!

Sam
fuente
1
¿Está utilizando la descarga TCP en la NIC a ambos lados? ¿Su uso de la descarga de TCP varía de 100M a 1G NIC? Si eso está en uso en cualquiera de los casos de prueba, puede valer la pena repetir las pruebas con eso desactivado solo para ver si el motor de descarga TCP en la NIC de 100M puede estar obstaculizando el funcionamiento de la comunicación 1G (este comentario es intencionalmente mano-ondulación solo para mencionar en general TOE)
FliesLikeABrick
¡Buena pregunta! La descarga de segmentación TCP está deshabilitada en ambos extremos. La descarga de segmentación genérica está habilitada en ambos extremos. También lo repetí con TSO habilitado, y no hizo ninguna diferencia notable.
Sam
Intente deshabilitar la descarga de segmentación genérica, al menos en el lado de 100M, y repita sus pruebas
FliesLikeABrick
Gracias por la sugerencia, pero no es una alegría: los mismos resultados con gso activado o desactivado en ambos lados.
Sam
1 Gbps a más de 150 ms proporciona un producto de retardo de ancho de banda muy grande, más de 18 Mb. ¿Qué sucede si golpeas tus buffers? tcp_*mem = 4096 1048576 33554432No ha habilitado Jumbo Frames en los enlaces de 1 Gbps, ¿verdad? Eso podría estar causando fragmentación en alguna parte.
suprjami

Respuestas:

1

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

HarryREN
fuente
Gracias, pero hemos probado todos esos. El retraso de WAN no es el problema: podemos alcanzar los 100Mbps casi de inmediato si usamos puertos de 100Mbps, pero tan pronto como uno cambie a 1Gbps, estaremos tostados.
Sam
1

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.

Sam
fuente
0

Repitiendo las mismas pruebas sobre UDP usando iperf, ¡el problema desaparece!

Los Ángeles (1 Gbps) a Londres (1 Gbps): rendimiento> 250 Mbps

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?

Jens Timmerman
fuente
Olvidé mencionar que el cliente es lento ... Si repetimos con dos clientes rápidos, entonces alcanzamos ~ 970Mbps bidireccionalmente.
Sam