Optimización del Rendimiento de Red en Linux Ajustando Parámetros sysctl de TCP/IP
Ajuste práctico de sysctl TCP en Linux para rendimiento, búferes, control de congestión y pruebas seguras.
Optimización del Rendimiento de Red en Linux Ajustando Parámetros sysctl de TCP/IP
La optimización del rendimiento de red en Linux comienza con una pregunta aburrida: ¿qué es realmente lento? Un servidor que alcanza un máximo de 300 Mbps en un enlace de 10 Gbps puede tener un problema de ventana TCP, un problema de disco, un problema de interrupciones de CPU, una mala configuración de NIC virtual, un problema de pérdida de paquetes o una aplicación que envía datos en fragmentos pequeños. El ajuste de sysctl solo ayuda con algunos de esos.
Por eso trato los cambios de sysctl TCP/IP como experimentos controlados, no como recetas mágicas de rendimiento. Comience con una línea base, cambie un pequeño grupo de configuraciones, pruebe de nuevo y tome notas. Si copia un bloque de ajuste gigante de internet en /etc/sysctl.conf, puede mejorar una carga de trabajo y perjudicar silenciosamente otra.
Las configuraciones a continuación son útiles cuando ejecuta servicios de alto rendimiento: repositorios de artefactos, servidores de respaldo, puertas de enlace de almacenamiento de objetos, proxies inversos ocupados, réplicas de bases de datos que envían grandes registros o hosts de Linux que mueven tráfico a través de enlaces de larga distancia. Es menos probable que ayuden si su cuello de botella es la CPU de cifrado TLS, el almacenamiento lento, el bloqueo de aplicaciones, los límites del proveedor de nube o la pérdida de paquetes fuera del host.
Antes de cambiar algo, recopile una línea base rápida:
ip -s link
ss -s
nstat -az | egrep 'TcpRetransSegs|TcpExtTCPLoss|TcpExtTCPTimeouts|TcpExtListenOverflows'
sar -n DEV,TCP,ETCP 1 10
iperf3 -c test-host -P 4 -t 30
Si ve que las retransmisiones aumentan, solucione la pérdida antes de aumentar los búferes. Si la CPU ya está al máximo en top, mpstat o perf, los sysctls pueden ocultar el síntoma pero no eliminar el cuello de botella. Si iperf3 es rápido pero su aplicación es lenta, mire la ruta de la aplicación antes de ajustar el kernel.
Cómo Encaja sysctl en el Ajuste de Red
sysctl expone parámetros del kernel mientras el sistema está en ejecución. Las configuraciones de red generalmente se encuentran bajo net.ipv4, net.ipv6 y net.core. Puede leer un valor así:
sysctl net.ipv4.tcp_congestion_control
sysctl net.ipv4.tcp_rmem
sysctl net.core.rmem_max
Puede probar un cambio temporal así:
sudo sysctl -w net.ipv4.tcp_congestion_control=bbr
Los cambios temporales desaparecen después de reiniciar. Los cambios persistentes deben estar en un archivo dedicado como /etc/sysctl.d/90-network-throughput.conf, no dispersos en /etc/sysctl.conf sin explicación.
sudo install -m 0644 /dev/null /etc/sysctl.d/90-network-throughput.conf
sudo editor /etc/sysctl.d/90-network-throughput.conf
sudo sysctl --system
Use un archivo separado porque la reversión es simple: mueva el archivo y ejecute sudo sysctl --system de nuevo. Eso importa cuando una configuración se comporta mal bajo tráfico de producción.
Búferes TCP: Dé Espacio a las Conexiones Largas para Respirar
El primer lugar donde la gente mira es el tamaño del búfer. TCP necesita suficiente espacio de ventana de envío y recepción para mantener datos en vuelo mientras los acuses de recibo viajan a través de la red. El modelo mental útil es el producto ancho de banda-retardo: una conexión de alto ancho de banda y alta latencia necesita más datos en vuelo que una conexión LAN de baja latencia.
Por ejemplo, una transferencia de 1 Gbps a través de una ruta de centro de datos de 1 ms necesita mucho menos datos en vuelo que una transferencia de 1 Gbps a través de una ruta WAN de 70 ms. Si la ventana de recepción es demasiado pequeña, el remitente se detiene aunque el enlace tenga espacio.
Linux utiliza arreglos de tres valores para el ajuste de memoria TCP:
net.ipv4.tcp_rmem = 4096 131072 33554432
net.ipv4.tcp_wmem = 4096 131072 33554432
Los tres números son los tamaños mínimo, predeterminado y máximo de búfer por socket en bytes. Los valores exactos deben coincidir con su carga de trabajo, presupuesto de memoria y comportamiento del kernel. El ejemplo anterior eleva el máximo a 32 MiB, que a menudo es suficiente para servidores ocupados sin ser imprudente. Algunos sistemas de larga distancia o con mucho almacenamiento usan valores más grandes, pero eso debe probarse con tráfico real.
Los límites de net.core limitan los búferes de socket:
net.core.rmem_max = 33554432
net.core.wmem_max = 33554432
Si tcp_rmem dice que TCP puede crecer hasta 32 MiB pero net.core.rmem_max es mucho menor, el límite inferior gana en la práctica. Mantenga los límites alineados con los máximos de TCP a menos que tenga una razón para no hacerlo.
No aumente los búferes a ciegas en una máquina con muchas conexiones concurrentes. Un servidor de archivos con unos pocos flujos grandes puede permitirse búferes por flujo más grandes. Un proxy que maneja cientos de miles de conexiones puede quemar memoria rápidamente si hace que cada socket sea elegible para búferes enormes.
El Ajuste Automático Ya Está Haciendo Algo de Trabajo
Los kernels modernos de Linux ya ajustan automáticamente los búferes TCP. Eso significa que generalmente no necesita establecer búferes de socket fijos enormes en la aplicación. El kernel aumenta los búferes cuando una conexión se beneficia de más espacio.
Su trabajo es principalmente asegurarse de que el techo no sea demasiado bajo. Si el rendimiento es pobre en una red larga y gruesa y ss -tin muestra ventanas de recepción pequeñas o un remitente bloqueado por el receptor, aumentar tcp_rmem, tcp_wmem, rmem_max y wmem_max puede ayudar.
Verifique las conexiones activas con:
ss -tin dst <ip-del-par>
Busque campos como cwnd, rtt, rto, bytes_acked, bytes_received y contadores de retransmisión. Cuentan una mejor historia que una sola prueba de velocidad.
Control de Congestión: CUBIC, BBR y Realidad
El algoritmo de control de congestión decide cómo TCP aumenta o reduce su tasa de envío. En muchos sistemas Linux, CUBIC es el predeterminado y funciona bien para tráfico general de internet y centro de datos. BBR puede mejorar el rendimiento y la latencia en algunas rutas con pérdidas o de larga distancia porque modela el ancho de banda del cuello de botella y el tiempo de ida y vuelta en lugar de reaccionar solo a la pérdida de paquetes.
Verifique los algoritmos disponibles:
sysctl net.ipv4.tcp_available_congestion_control
sysctl net.ipv4.tcp_congestion_control
Habilite BBR solo si su kernel lo tiene disponible:
sudo sysctl -w net.ipv4.tcp_congestion_control=bbr
Para persistencia:
net.ipv4.tcp_congestion_control = bbr
Algunos sistemas también requieren el planificador de colas de fair queuing para un buen comportamiento de BBR:
net.core.default_qdisc = fq
No asuma que BBR siempre es más rápido. Puede cambiar la equidad con otros flujos, y diferentes versiones de BBR se comportan de manera diferente entre kernels. Pruébelo en el mismo patrón de tráfico que le importa: muchas llamadas API pequeñas, unas pocas transferencias masivas, tráfico de base de datos replicado o carga mixta similar a la producción.
Colas de Escucha: Solucione las Pérdidas Antes de que se Conviertan en Misterios
Los problemas de rendimiento a veces se manifiestan como fallos de conexión durante picos de tráfico. Si un servicio acepta nuevas conexiones TCP más lentamente de lo que los clientes las crean, las colas del kernel se llenan.
Configuraciones relevantes:
net.core.somaxconn = 4096
net.ipv4.tcp_max_syn_backlog = 8192
somaxconn limita el backlog de conexiones completadas solicitado por las aplicaciones a través de listen(2). tcp_max_syn_backlog afecta la capacidad de la cola SYN semiabierta. Aumentarlos puede ayudar a servidores web ocupados, proxies y balanceadores de carga, pero la aplicación también debe solicitar un backlog suficientemente grande. Nginx, HAProxy, Envoy y los servidores de aplicaciones a menudo tienen sus propias configuraciones de backlog.
Vigile los desbordamientos:
nstat -az | egrep 'ListenOverflows|ListenDrops|Syncookies'
ss -ltn
Si ListenOverflows aumenta, las colas del kernel no están al día. Si la CPU está saturada o la aplicación está bloqueada por servicios posteriores, aumentar los tamaños de cola puede reducir los errores del cliente brevemente pero no solucionará el servicio.
Backlog y Procesamiento de Paquetes
net.core.netdev_max_backlog controla cuántos paquetes pueden esperar en la cola de entrada cuando el kernel recibe paquetes más rápido de lo que puede procesarlos.
net.core.netdev_max_backlog = 250000
Esto puede ayudar en interfaces de alta velocidad durante ráfagas, especialmente con redes virtualizadas. También puede agregar latencia si convierte el host en una gran sala de espera de paquetes. Primero verifique las pérdidas de interfaz:
ip -s link show dev eth0
ethtool -S eth0 | egrep 'drop|err|timeout|miss|fifo'
Si las pérdidas a nivel de controlador están aumentando, también inspeccione los tamaños de anillo de NIC, la distribución de interrupciones, las colas RSS y la afinidad de CPU. Eso está fuera de sysctl, pero a menudo importa más que los búferes TCP en hosts de 10 Gbps y más rápidos.
TIME_WAIT y Agotamiento de Puertos
Los clientes, proxies y ejecutores de trabajos de alto rendimiento pueden quedarse sin puertos efímeros o acumular muchos sockets en TIME_WAIT. Tenga cuidado aquí porque los consejos de ajuste antiguos pueden ser dañinos.
Verifique el rango actual:
sysctl net.ipv4.ip_local_port_range
ss -tan state time-wait | wc -l
Un ajuste razonable del lado del cliente es ampliar el rango de puertos efímeros:
net.ipv4.ip_local_port_range = 10240 60999
Evite consejos antiguos que recomiendan tcp_tw_recycle; fue eliminado de Linux porque rompía el tráfico válido, especialmente detrás de NAT. tcp_tw_reuse existe en muchos kernels, pero su comportamiento ha cambiado con el tiempo. No lo habilite como una configuración de rendimiento predeterminada. Si cree que lo necesita, pruebe su kernel exacto y patrón de tráfico cuidadosamente.
Para servidores, un montón de sockets TIME_WAIT a menudo es normal. Para clientes, el agotamiento de puertos generalmente significa que necesita agrupación de conexiones, keep-alive, HTTP/2, menos conexiones salientes de corta duración o más IPs de origen.
Un Archivo de Inicio Conservador
Aquí hay un punto de partida práctico para un servidor de alto rendimiento. Intencionalmente no es extremo:
# /etc/sysctl.d/90-network-throughput.conf
# Techos de ajuste automático TCP más grandes para rutas de alto ancho de banda o mayor latencia.
net.core.rmem_max = 33554432
net.core.wmem_max = 33554432
net.ipv4.tcp_rmem = 4096 131072 33554432
net.ipv4.tcp_wmem = 4096 131072 33554432
# Colas más grandes para tráfico entrante en ráfagas.
net.core.somaxconn = 4096
net.ipv4.tcp_max_syn_backlog = 8192
net.core.netdev_max_backlog = 250000
# Opcional: pruebe antes de habilitar globalmente.
# net.core.default_qdisc = fq
# net.ipv4.tcp_congestion_control = bbr
Aplíquelo:
sudo sysctl --system
Luego mida de nuevo. Use el mismo tamaño de prueba, ventana de tiempo, número de flujos paralelos y ruta de red. Una prueba de antes y después que cambia cinco variables no es evidencia.
Errores Comunes
El primer error es ajustar en una ruta con pérdidas. TCP ve la pérdida como congestión. Búferes más grandes pueden aumentar un poco el rendimiento, pero también pueden aumentar la latencia y ocultar el problema real. Primero solucione cables defectuosos, conmutadores virtuales sobrecargados, policía de paquetes, desajuste de MTU y rutas VPN inestables.
El segundo error es asumir que iperf3 -P 8 prueba el rendimiento de la aplicación. Los flujos paralelos pueden llenar un enlace incluso cuando una conexión de aplicación real no puede. Eso es información útil, pero no es toda la historia.
El tercer error es establecer búferes enormes en hosts compartidos. Techos más grandes están bien cuando el kernel aumenta los búferes solo según sea necesario, pero la presión de memoria lo cambia todo. Monitoree free, slabtop, la memoria TCP y la memoria de la aplicación después de los cambios.
El cuarto error es olvidar la reversión. Mantenga los valores anteriores en su ticket de cambio o runbook:
sysctl -a | egrep 'net.core.rmem_max|net.core.wmem_max|net.ipv4.tcp_rmem|net.ipv4.tcp_wmem|net.ipv4.tcp_congestion_control'
Cuando sysctl No es la Solución
Si un núcleo de CPU está al máximo mientras otros están inactivos, mire el manejo de interrupciones, RSS, RPS/XPS y el subprocesamiento de la aplicación. Si la espera de disco es alta, la red puede estar esperando almacenamiento. Si TLS consume CPU, pruebe con y sin cifrado y considere hardware, elección de cifrado o reutilización de conexiones. Si Kubernetes o un balanceador de carga en la nube está en la ruta, verifique los límites a nivel de servicio y las tablas de conntrack.
Para hosts con mucho NAT, también inspeccione conntrack:
sysctl net.netfilter.nf_conntrack_count
sysctl net.netfilter.nf_conntrack_max
Eso no es ajuste de rendimiento TCP, pero el agotamiento de conntrack puede parecer lentitud aleatoria de red o conexiones caídas.
Pruebas Sin Engañarse a Sí Mismo
Use iperf3 como una herramienta de red, no como prueba de que la aplicación está arreglada. Una prueba de un solo flujo es útil porque muestra lo que una conexión TCP puede hacer:
iperf3 -c test-host -t 30
Una prueba paralela muestra si el enlace puede ser llenado por múltiples flujos:
iperf3 -c test-host -P 8 -t 30
Si los flujos paralelos son rápidos pero un flujo es lento, mire el control de congestión, el crecimiento de la ventana TCP, RTT y pérdida de paquetes. Si ambos son lentos, mire más abajo: errores de interfaz, límites de ancho de banda de la nube, saturación de CPU, MTU, inspección de firewall o almacenamiento detrás del remitente y receptor.
Mantenga la ruta de prueba realista. Probar dos hosts en el mismo rack no le dirá mucho sobre un trabajo de respaldo que cruza regiones. Probar con un archivo pequeño no expondrá el rendimiento en estado estable. Probar a través de una VPN puede medir el dispositivo VPN más que el TCP de Linux.
Después de cada cambio, capture los mismos contadores:
nstat -az > /tmp/nstat-after.txt
ss -s
sar -n DEV,TCP,ETCP 1 10
El resultado útil no es solo "el número subió". Quiere saber si las retransmisiones cayeron, las colas dejaron de desbordarse, la CPU se mantuvo razonable y la latencia no empeoró para solicitudes más pequeñas.
El buen ajuste de red en Linux se mide y es reversible. Aumente los techos de búfer TCP cuando la ruta necesite ventanas más grandes. Pruebe el control de congestión en lugar de asumir que un algoritmo gana en todas partes. Aumente las colas de escucha cuando vea pérdidas de cola, y arregle la aplicación si no puede aceptar lo suficientemente rápido. sysctl es útil, pero es una capa en un sistema más grande.