Muestro cómo softirq cpu junto con NAPI, la distribución de IRQ y el diseño de colas limitan o liberan el rendimiento de la red en el alojamiento. Con puntos de medición claros, sintonización dirigida y afinidades limpias, reduzco Latencias y aumentar sistemáticamente el rendimiento pps en los servidores productivos.
Puntos centrales
Estas ideas centrales transportan los paquetes de red de forma eficiente a través de la CPU, el núcleo y la NIC, y mantienen los tiempos de respuesta al mínimo. constante bajo.
- Presupuesto NAPI ajuste fino: Más paquetes por sondeo reducen los gastos generales y suavizan el Carga de la CPU.
- Equilibrio de IRQ y afinidad: evitar puntos calientes, aumentar los aciertos de caché, Picos de latencia Pulse.
- Cola múltiple, RSS/RPS/XPS: paralelización de flujos, mantenimiento de la alineación NUMA, pps aumentar.
- Descarga utilizar conscientemente: GRO/LRO, TSO, evaluar la coalescencia, Jitter vigilar.
- Aislamiento y Busy Polling: tiempos de respuesta predecibles en aplicaciones dedicadas. Núcleos.
Conceptos básicos: Qué ocurre en el núcleo durante el tráfico de red
Un paquete primero aterriza en una interrupción de hardware, después de lo cual el núcleo se hace cargo del trabajo en SoftIRQs y los bucles de sondeo NAPI. Me aseguro de que la fase rápida HardIRQ sigue siendo muy corta y que la lógica real se mueve al contexto correcto para que el tiempo de CPU no se agota. Los hilos ksoftirqd sólo intervienen si no es posible el procesamiento directo, lo que conduce rápidamente a colas bajo carga continua. Aquí es exactamente donde se produce el tiempo de espera, que se refleja en un aumento del TTFB y un rendimiento fluctuante. Si quieres profundizar, puedes encontrar conocimientos prácticos sobre el procesamiento de IRQ en este artículo sobre Gestión de interrupciones y rendimiento de la CPU, que utilizo para la categorización.
NAPI, SoftIRQs y ksoftirqd: controlar la latencia en lugar de gestionarla
NAPI reduce las tormentas de interrupciones recogiendo varios paquetes por ejecución dentro de un presupuesto definido y minimizando así el tiempo de interrupción. Sobrecarga baja. Si el presupuesto es insuficiente, los paquetes se amontonan, el ksoftirqd se calienta y el Latencia aumenta de forma apreciable. En tales situaciones, compruebo sistemáticamente /proc/softirqs y /proc/net/softnet_stat para visualizar caídas, time_squeeze o colas desbordadas. A continuación, aumento gradualmente net.core.netdev_budget o net.core.netdev_budget_usecs y controlo en paralelo la carga de la CPU, la distribución p95/p99 y las pérdidas de paquetes. El truco está en hacer suficiente trabajo por sondeo sin saturar la ejecución interactiva de los hilos de usuario.
Equilibrio y afinidad de IRQ: evite los puntos calientes, aumente los aciertos de caché.
Un único núcleo con todas las IRQs de la NIC se convierte en un cuello de botella porque tiene que servir interrupciones, IRQs suaves así como hilos de aplicaciones; por lo tanto, distribuyo IRQs con objetivos concretos. El servicio irqbalance ayuda, pero para altas tasas de pps asigno explícitamente colas RX/TX mediante afinidad a colas adecuadas. núcleos. En los sistemas NUMA, vinculo las colas a núcleos del mismo nodo para evitar accesos remotos a la memoria. Los hilos de la aplicación se ejecutan en núcleos vecinos pero separados, lo que mejora la localización de la caché y la programabilidad. Esta guía de distribución estratégica ofrece una buena visión general de la Equilibrio de IRQ en el centro de datos, que utilizo como referencia para afinar.
Cola múltiple, RSS/RPS/XPS: uso correcto de la paralelización
Las NIC modernas vienen con varias colas RX/TX, que puedo controlar mediante RSS a los flujos y lograr así un paralelismo real. Si la tarjeta ofrece muy pocas colas, utilizo RPS/XPS para realizar ajustes en el software con el fin de distribuir los paquetes de forma razonable entre los flujos. núcleos para empujar. La distribución limpia de hash es importante para que un flujo permanezca siempre en la misma CPU y no se produzcan costosas distorsiones de caché. Al mismo tiempo, mantengo las rutas TX y RX cerca para evitar la contención de bloqueos y accesos innecesarios entre nodos. Esto aumenta el rendimiento en pps sin que un solo núcleo tire de los frenos.
Afinidad de la CPU hasta el espacio de usuario: pensamiento integral
Planifico la ruta de datos desde el NIC-IRQ a través de las colas NAPI hasta los hilos worker de la app para que los paquetes lleguen a su destino sin enganches innecesarios y el Tiempo de respuesta permanece constante. Para conseguirlo, separo sistemáticamente los núcleos para interrupciones/softIRQs de los núcleos de aplicación y creo núcleos claros de Afinidad-reglas. A los servidores web, proxies inversos y bases de datos se les asignan conjuntos de CPU fijos que están cerca de los núcleos IRQ para mantener las rutas cortas. Además, establezco el gobernador de CPU en rendimiento para que los cambios de reloj no empujen el jitter a p99. Esta asignación coherente hace que el comportamiento sea predecible y ayuda a diagnosticar los cuellos de botella de forma limpia.
Descargas, GRO/LRO, cortafuegos y eBPF: ahorre carga sin ir a ciegas
Descarga de sumas de comprobación, TSO y coalescencia tiempo de CPU, Sin embargo, pueden cambiar el tamaño de los paquetes, el comportamiento de las ráfagas y el jitter, que es por lo que mido los efectos específicamente. GRO/LRO agrupan las tramas y alivian la pila, pero para los requisitos en tiempo real decido según la situación sobre Desactivación o de uso limitado. Las tablas Conntrack y las profundas cadenas nftables/iptables cuestan relojes, así que ordeno las reglas superfluas y simplifico las rutas. Si es necesario, recurro a eBPF (XDP, tc-BPF) para tomar decisiones tempranas en el NIC y evitar rutas costosas. Un buen punto de partida para la práctica del ajuste fino es este resumen de Coalescencia de interrupciones, que tengo en cuenta para los presupuestos sensibles a la latencia.
Polling ocupado y aislamiento de la CPU: bloqueo de los tiempos de respuesta
Para los objetivos de latencia dura, utilizo el sondeo ocupado para que los sockets del espacio de usuario recojan los paquetes incluso antes y Tiempos de espera acortar. Esto aumenta la carga, pero me proporciona p99 distribuciones muy estrechas para la API o el comercio de las cargas de trabajo en dedicado Núcleos. Además, aíslo los núcleos con isolcpus=, nohz_full= y rcu_nocbs= para que los temporizadores, RCU y los servicios del sistema sólo se ejecuten en las CPUs de mantenimiento. Esta separación evita interferencias en los núcleos de latencia y hace que el comportamiento sea reproducible. El resultado es una hoja de ruta clara: núcleos dedicados, recogida temprana de paquetes, presupuestos definidos.
Control y resolución de problemas: del síntoma a la causa
Empiezo con los pps, el rendimiento y la carga del núcleo, luego compruebo las caídas y la actividad del ksoftirqd-hilos a lo largo del tiempo para reconocer patrones de forma fiable. Herramientas como sar, htop, ss, nload y ethtool me muestran cuándo y dónde se produce la congestión y si la Cues alcanzan sus límites. Las distribuciones son importantes en lugar de los valores medios para que no se pierdan los picos nocturnos, las ventanas cron o las campañas. Correlaciono los picos de TTFB con la distribución de IRQ, el presupuesto NAPI y los ajustes de descarga para realizar ajustes específicos. Una afinidad IRQ ajustada o un nuevo presupuesto NAPI es a menudo suficiente para reducir notablemente los tiempos de espera.
Los parámetros de ajuste de un vistazo
El siguiente resumen me ayuda a utilizar los cambios con prudencia y a asignar los efectos con claridad antes de realizar cambios permanentes. lanzamientos plan. Pruebo cada ajuste de forma iterativa, mido las distribuciones de latencia y observo los efectos secundarios en CPU y la memoria. Sólo cambio un punto por ventana de prueba para que la causa y el efecto queden claros. Después documento los resultados y establezco valores umbral para las alertas. De este modo, consigo mejoras reproducibles sin arriesgarme a sorpresas en el tráfico productivo.
| Parámetro/Característica | Efecto en la ruta de datos | Cuándo aumentar/activar | Riesgos/efectos secundarios |
|---|---|---|---|
| net.core.netdev_budget | Más paquetes por encuesta NAPI | Para gotas en softnet_stat | Las encuestas más largas desplazan a los hilos de usuarios |
| net.core.netdev_budget_usecs | Limitar la ventana de tiempo por sondeo | Para fluctuaciones debidas a grandes ráfagas | Demasiado pequeño: más cambios de contexto |
| RSS/RPS/XPS | Distribuir flujos entre núcleos | Para puntos calientes en un núcleo | Hashes incorrectos: distorsiones de caché |
| Afinidad IRQ | Vincular IRQs cerca del núcleo | Con NUMA-Missmatch | La mala asignación crea nuevos puntos calientes |
| GRO/LRO/TSO | Reduce el número de paquetes | Para el cuello de botella de la CPU | Jitter, ráfagas más grandes |
| Sondeo ocupado | Recogida anticipada de paquetes | Para objetivos difíciles de p99 | Más consumo de CPU |
Anillos RX/TX y profundidad de cue: dimensiona correctamente los buffers
Incluso con IRQ bien distribuidas y presupuestos adecuados, los anillos de NIC demasiado pequeños o demasiado grandes pueden mermar el rendimiento. Por ello, compruebo los tamaños de anillo RX/TX de la tarjeta y los adapto a los objetivos de carácter de ráfaga y latencia. Los anillos demasiado pequeños provocan caídas en la NIC durante los picos de tráfico, visibles como rx_missed_errors o fifo_errors en las estadísticas del controlador. Los anillos demasiado grandes ocultan la congestión, aumentan la latencia y crean largos bordes de fuga en p95/p99. Busco el término medio: suficiente búfer para absorber ráfagas cortas, pero no tanto como para que los paquetes “envejezcan” en las colas.
Además, miro el host-side tx_queue_len y el Qdisc utilizado. Con sch_fq o fq_codel, puedo suavizar el comportamiento de las ráfagas y distribuir grandes paquetes TSO mediante pacing. Esto reduce las microrráfagas en el puerto del conmutador y suaviza la curva de latencia, algo importante para las cargas de trabajo mixtas en las que se ejecutan pequeñas RPC junto con grandes cargas. Superviso las estadísticas ethtool y las correlaciono con softnet_stat para reconocer si la congestión se produce en el anillo NIC, en el backlog netdev o en el Qdisc.
MTU, tramas jumbo y segmentación
El MTU es una palanca clásica que a menudo se subestima. Las tramas jumbo reducen el número de paquetes por Gbit/s y reducen la carga de la CPU, pero sólo si la ruta es realmente apta para jumbo de extremo a extremo. Por eso, valido sistemáticamente las estaciones remotas, los conmutadores y los túneles. En cuanto hay fragmentación de vuelta a 1500 en alguna parte, hay riesgo de problemas de MTU de ruta, retransmisiones e innecesarias Jitter. En los centros de datos con comunicación Este/Oeste dominante, merece la pena una estrategia 9k homogénea, mientras que 1500 suele ser la opción más estable para las cargas de trabajo orientadas a Internet.
Siempre evalúo la MTU junto con TSO/GSO/GROUn agrupamiento demasiado agresivo puede dar lugar a grandes ráfagas en el TX que llenen los búferes de subida y generen picos de latencia. El objetivo es una ruta coherente: segmentación sensata en el transmisor, mecanismos de ritmo suficientes y GRO que ahorre trabajo en el lado del receptor sin frustrar los requisitos de tiempo real.
UDP, QUIC y cargas de trabajo de streaming: consideraciones específicas
No todo el tráfico es TCP. UDP-Los perfiles pesados (DNS, VoIP, QUIC, telemetría) se comportan de forma diferente en RSS/RPS y GRO. Las pilas modernas admiten UDP-GRO/GSO, que puede reducir la carga de la CPU: yo lo utilizo de forma selectiva y mido si aumentan los riesgos de reordenación o el jitter. Para cargas QUIC/HTTP3, la distribución limpia de flujos es crucial: RPS puede ayudar si la NIC ofrece muy pocas colas RSS, pero no debe “tirar” ningún flujo de caché caliente. En el lado TX configuro XPS para agrupar las rutas de transmisión y reducir la contención de bloqueos. En la práctica, una asignación silenciosa y afín al núcleo merece la pena, especialmente con muchos flujos UDP de tamaño medio en los que cada golpe de caché cuenta.
Virtualización y contenedores: integración limpia de host, guest y vhost
En entornos virtualizados, el trabajo cambia entre el host, los hilos del vhost y las IRQ del huésped. Me aseguro de que vhost-net-threads reciben sus propios núcleos y no colisionan con app workers. Sus afinidades deben coincidir con las colas RX/TX físicas, de lo contrario se producirá una migración innecesaria entre CPU. En el huésped, compruebo las colas de virtio-net, activo las colas múltiples y configuro RSS/RPS de forma análoga a bare metal. Donde la latencia y los pps están en primer plano SR-IOV reducir aún más los gastos generales - el requisito previo es una topología NUMA coherente: VF, vCPU y memoria pertenecen al mismo nodo.
En la pila de contenedores, las redes superpuestas, las cadenas NAT profundas y las topologías CNI complejas provocan saltos adicionales. Para los servicios de latencia crítica, prefiero hostNetwork o redes magras (macvlan/ipvlan), igualar las rutas NAT y mantener Conntrack lo más pequeño posible. Es importante una estrategia de CPU coherente: los núcleos IRQ y NAPI del host deben estar situados en la vecindad de los núcleos en los que se ejecutan los vhost/container workers - es la única forma de mantener la ruta de datos corta y predecible.
Programación, estados C y subprocesos IRQ
Porque la latencia no es sólo tiempo de cálculo, sino también Hora de despertarse Minimizo los estados C profundos en los núcleos de latencia. Un powersave agresivo puede costar milisegundos antes de que se ejecute una SoftIRQ. Por tanto, confío en los reguladores de rendimiento, limito los estados C profundos y mantengo el turbo consistente para que los saltos de frecuencia sean predecibles. Igualmente importante es Enhebrado IRQCuando los controladores lo permiten, muevo el trabajo a los hilos IRQ y priorizo para que RX se inicie antes que el trabajo posterior sin desplazar completamente a userland. La interacción de las políticas de programación, afinidades y presupuestos es complicada; pruebo paso a paso, registro p99 y vigilo las interferencias con ksoftirqd, que de lo contrario se convierte en un cuello de botella secreto.
Observación en profundidad: tracepoints, contadores, histos
Si las métricas siguen siendo imprecisas, voy un nivel más allá: utilizo tracepuntos del núcleo en torno a netif_receive_skb, napi_poll y net_dev_queue, para ver la duración de los sondeos, la cantidad de paquetes y los tiempos de espera en forma de histogramas. Estas distribuciones muestran si 1 % de los sondeos están tardando demasiado o si se están agotando las colas individuales. Además, ethtool-rx/tx-counters, TCP retransmits, busy poll hits y softnet_stat indican claramente dónde se están perdiendo paquetes. Utilizo el análisis de caídas para reconocer si la NIC se está cayendo (anillo lleno), el backlog de netdev se está colapsando (time_squeeze) o el Qdisc/firewall se está ralentizando. Sólo cuando estas piezas del rompecabezas encajan, ajusto los anillos, los presupuestos o las descargas.
Racionalice las vías de seguridad y filtrado
ACLs complejas, cadenas nftables/iptables profundas y amplias tablas conntrack añaden latencia constante por paquete. Yo consolido reglas, trabajo con conjuntos/mapas y muevo las caídas genéricas lo más adelante posible en la ruta - idealmente tan pronto como sea posible en la NIC (XDP/clsact) si la latencia es crítica. Los flujos sin estado, la telemetría o los puertos “seguros” conocidos pueden utilizarse de forma selectiva. sin seguimiento para eliminar la necesidad de costosas búsquedas. Al mismo tiempo, mantengo las tablas de estado actualizadas, ajusto los tamaños hash a los picos de carga y ordeno agresivamente las entradas huérfanas. El objetivo es una ruta de política limpia y rastreable que no se note en el perfil como una carga permanente.
Antipatrones típicos y cómo los evito
- Todas las IRQ en un núcleo: conduce a la congestión y ksoftirqd caliente. Antídoto: afinidades dirigidas por taco, coherentes con NUMA.
- Maximización ciega de anillos/presupuestos: oculta la congestión, aumenta las colas de latencia. Antídoto: aumentar gradualmente, medir las distribuciones.
- Configuración incorrecta del hash de flujo: Los flujos saltan entre núcleos, las cachés se desvanecen. Antídoto: claves RSS estables, RPS/XPS sólo con un objetivo claro.
- Hilos de aplicación en los mismos núcleos que SoftIRQs: Interferencias y fluctuaciones. Antídoto: separación dura, asignación por vecinos.
- Overlays/NAT sin presupuesto: a cada salto. Solución: racionalice las rutas y aloje redes para cargas de trabajo con latencia.
- Ahorro de energía en los núcleos de latencia: Los estados C profundos ralentizan la reacción. Antídoto: regulador de rendimiento, limitación del estado C.
- Descarga sin medición: TSO/GRO puede exacerbar las ráfagas y las fluctuaciones. Remedio: Activar carga de trabajo específica, monitorizar p99.
Acogida práctica: pasos que funcionan
Empiezo con una fase de medición limpia, establezco líneas de base y mantengo todos los cambios pequeños en ventanas de tiempo cortas para poder Causas pueden separarse. A continuación, activo irqbalance, compruebo la distribución automática y, si es necesario, establezco afinidades manuales hasta que no haya Puntos de acceso ya no son visibles. A continuación, configuro Multi-Queue, RSS y, si es necesario, RPS/XPS, sincronizados con NUMA. Vinculo los app workers a núcleos cercanos a sus núcleos IRQ, pero sin colisión directa. Por último, purgo las rutas del cortafuegos, compruebo las tablas conntrack y tomo decisiones conscientes sobre las descargas basadas en objetivos de latencia.
Ejemplo de libro de jugadas para p99 latencias
Primero mido p95/p99 mediante carga representativa y aseguro los logs de /proc/softirqs y /proc/net/softnet_stat para Gotas y time_squeeze son claramente visibles. A continuación, aumentar netdev_budget o netdev_budget_usecs paso a paso y mantenga p99 después de cada cambio para que pueda ver real Tendencias reconocer. Paralelamente, asocio IRQs a los núcleos de un nodo NUMA y muevo los app workers a los vecinos adecuados. Si p99 sigue saltando, pruebo variantes de GRO/LRO y perfiles de coalescencia de interrupciones, cada uno con una ruta de medición corta. Sólo cuando la distribución permanece estable transfiero la configuración a roles Ansible o dropins systemd.
Versión corta para administradores
Logro el mayor efecto multiplicador SoftIRQs, Presupuesto NAPI, afinidades IRQ e hilos de aplicación como una ruta de datos coherente. Distribuyo el trabajo de red entre los núcleos, mantengo colas coherentes con NUMA y conecto los trabajadores de forma sensata para que Rutas ser breve. Configuro las descargas deliberadamente y mido el jitter en lugar de optimizar ciegamente el rendimiento. Para los objetivos de latencia difíciles, confío en el sondeo ocupado y el aislamiento de la CPU, mientras que las CPU de mantenimiento interceptan las interferencias. Si se aplican estos pasos de forma disciplinada, se obtiene un rendimiento constante, distribuciones de latencia más estrechas y un entorno de alojamiento que reacciona de forma predecible a los picos de carga.


