Optimizo las rutas de red de un servidor mediante Afinidad IRQ y asignar colas RX/TX a los núcleos para controlar la latencia, el rendimiento y la fluctuación p99. Quienes utilizan CPU multinúcleo orquestan sistemáticamente las interrupciones, SoftIRQs, NAPI y NUMA de forma que los flujos permanezcan afines a los núcleos, se reduzcan los cambios de contexto y la aplicación responda con una rapidez apreciable.
Puntos centrales
- Distribución IRQ determina qué núcleos llevan interrupciones de hardware y evita los hotspots.
- Proximidad NUMA reduce el acceso remoto y disminuye los picos de latencia.
- SoftIRQs y NAPI controlar el procesamiento por lotes y reducir la carga de los núcleos.
- RPS/RFS mantiene los flujos cerca de los hilos consumidores.
- Medición y fijación hace que el rendimiento sea más determinista.
Por qué la afinidad IRQ cuenta en el funcionamiento del servidor
Las altas tasas de paquetes ponen rápidamente a prueba los núcleos individuales si todas las interrupciones recaen en unas pocas CPU, por lo que distribuyo la carga de forma selectiva con el fin de Puntos de acceso para evitarlo. Asigno colas RX/TX a los núcleos apropiados para mantener las rutas de datos cortas y las cachés calientes. Esto reduce las latencias p95/p99 porque evito migraciones innecesarias y mantengo los pasos de procesamiento en los mismos núcleos. Tengo en cuenta la proximidad física de la NIC, los canales de memoria y los zócalos de la CPU para que la ruta desde el paquete hasta el trabajador de la aplicación se mantenga siempre rápida. Esta afinidad de núcleos crea una estabilidad mensurable durante los picos de tráfico sin tener que actualizar el hardware inmediatamente.
Equilibrio de IRQ frente a afinidad fija
El servicio estándar irqbalance distribuye las interrupciones automáticamente, pero desconoce la lógica de mi aplicación, los objetivos NUMA y los presupuestos de latencia. Vinculo las IRQ de red críticas a los núcleos seleccionados, mientras que las interrupciones ruidosas o menos importantes se mueven a otros núcleos. Esta vinculación se armoniza con el pinning de los procesos de la aplicación, de modo que el pipeline por flujo se mantiene coherente. Con mucho tráfico, evito las redistribuciones que generan sobrecarga adicional y debilitan el efecto caché. Si quieres profundizar más, puedes encontrar información práctica de fondo en esta guía: Equilibrio de IRQ en el centro de datos.
Afinidad de CPU, NUMA y la ruta corta de datos
Prefiero conectar las IRQs de aplicación y de red a la misma NUMA-para que los accesos a memoria sigan siendo locales. Si un NIC se cuelga en el nodo 0, también coloco allí las colas de RX asociadas y enlazo los procesos relevantes a estos núcleos. De este modo, evito los costosos accesos remotos a la memoria, que tienen un gran impacto en la latencia a altas velocidades de paquetes. También incluyo pares hyper-threading para que los hilos hermanos no interfieran entre sí. Este triángulo de anclaje de procesos, afinidad de IRQ y topología NUMA hace que las rutas de red sean más predecibles y aumenta el rendimiento.
Comprensión de SoftIRQs, NAPI y diseño de colas
Tras la interrupción por hardware, el núcleo se hace cargo del procesamiento en SoftIRQs, a menudo en el mismo núcleo que recibió la IRQ. Cuando la carga es alta, distribuyo conscientemente la carga de SoftIRQ para aliviar los cuellos de botella sin fragmentar innecesariamente la ruta de datos. Las NIC de varias colas ayudan porque puedo asignar núcleos claramente definidos a cada cola y conseguir así una verdadera paralelización. Utilizo NAPI para procesar paquetes por lotes, de modo que no se produzcan tormentas de interrupciones y el tiempo de CPU se utilice de forma eficiente. Este artículo proporciona información básica sobre esta ruta: SoftIRQ y rendimiento de la red.
RPS/RFS y localización de flujos
Utilizo RPS para una distribución más amplia de los paquetes y uso RFS para que los flujos acaben en los hilos consumidores. Esto mantiene la eficiencia de los accesos a la caché y la aplicación se beneficia de tiempos de respuesta consistentes. Armonizo la estrategia hash de la NIC, el número de colas y los conjuntos de CPU RPS para que no se desborde ninguna cola del núcleo. La afinidad de flujos es especialmente eficaz para muchas peticiones cortas, como las generadas por API y microservicios. De este modo, construyo una canalización en la que cada flujo toca el mismo núcleo con la mayor frecuencia posible y evito migraciones innecesarias.
RSS, tabla de indirecciones y XPS: control específico del hashing
Para garantizar que la distribución se inicia limpiamente en el NIC, ajusto RSS (Receive Side Scaling) y la tabla de indirección para que las colas RX se asignen exactamente a los núcleos que más tarde llevarán los hilos de la aplicación. Me aseguro de que el número de colas coincida con el número de núcleos utilizados y de que las claves hash permanezcan estables para que los flujos no se desvíen inesperadamente. Si el algoritmo hash cambia o la tabla de indirección se sobrescribe dinámicamente, se rompe la localidad del flujo y se producen pérdidas de caché.
En la ruta TX, activo adicionalmente XPS (Transmit Packet Steering) para que los paquetes salientes sean enviados por el núcleo que está procesando la aplicación. Esto también mantiene las cachés TX cerca del trabajador, y el camino desde la cola del socket a la cola de la NIC permanece corto. Mantengo los mapeos RX y TX consistentes, los documento por interfaz y los defino en scripts de arranque para que un reinicio no desdibuje la arquitectura.
Coalescencia de interrupciones: sopesar latencia y rendimiento
Con Coalescente Resumo las interrupciones para reducir la sobrecarga, pero presto atención a los límites de latencia de mi aplicación. Para streaming y VoIP, tiendo a mantener los intervalos cortos, mientras que las transferencias masivas toleran bien lotes más largos. Hago pruebas paso a paso, mido p95/p99 y compruebo las caídas, las retransmisiones y la utilización de la CPU por núcleo. Sólo entonces anoto los ajustes y los documento para cada host y NIC. Este artículo práctico ofrece una visión más profunda de la compensación: Explicación de la coalescencia de interrupciones.
Dosificar correctamente las descargas y la agregación
He puesto GRO/LRO para reducir la sobrecarga de la CPU, pero comprueba si mis cargas de trabajo se benefician de lotes más grandes. Las API sensibles a la latencia suelen responder mejor cuando GRO es moderado y LRO está desactivado, porque los superpaquetes grandes pueden exacerbar los efectos de bloqueo de cabecera. Para transferencias masivas, replicación o copias de seguridad, utilizo GRO/GSO/TSO de forma más agresiva siempre que el lado del receptor permanezca estable y la utilización de la CPU disminuya.
Descarga de sumas de comprobación y TSO/GSO reducir significativamente la carga de la CPU, pero me aseguro de que los middleboxes, los túneles o las incompatibilidades de las descargas (por ejemplo, con determinadas encapsulaciones) funcionen correctamente. Si se producen anomalías, reduzco gradualmente las descargas individuales y mido los efectos sobre el rendimiento, las retransmisiones y el tiempo de CPU. El objetivo es conseguir un conjunto que se mantenga estable en general y predecible en los momentos de máxima carga.
Aislamiento de la CPU, planificador y estados de energía
Para los presupuestos de latencia dura, aíslo los núcleos para las rutas de red y los app workers. Con Aislamiento de la CPU y una estrategia de limpieza eficiente, evito que las tareas del sistema, los Kthreads o las interrupciones del temporizador lleguen a los núcleos „calientes“. También arreglo el Gobernador de CPU al „rendimiento“ y limitar la profundidad Estados C, si estos causan latencias de despertar. Yo vigilo las temperaturas del núcleo, ya que de lo contrario la putrefacción térmica puede arruinar cualquier retoque.
La elección de Programación de clases influye en la previsibilidad. Doy prioridad a los hilos relacionados con la red, pero no los ejecuto de forma agresiva y exclusiva, para que no compitan con ksoftirqd por el tiempo de CPU. Compruebo regularmente si ksoftirqd se está iniciando en núcleos individuales, una clara señal de que la carga de SoftIRQ es demasiado alta o está mal distribuida.
Encuestas y rutas de baja latencia
Cuando los microsegundos cuentan, pongo Sondeo ocupado de forma selectiva. Las aplicaciones pueden definir ventanas de sondeo para sockets seleccionados, de modo que extraigan paquetes directamente de los presupuestos de NAPI sin esperar interrupciones. Elijo intervalos de sondeo cortos para evitar quemar tiempo de CPU y limitar esta técnica a rutas calientes con tráfico constante. Paralelamente, adapto presupuestos netdev moderadamente para que los lotes sean lo suficientemente grandes sin matar de hambre al resto del sistema.
Disciplina y ritmo de las colas de red
Configuré el qdisc por interfaz para adaptarse a la carga de trabajo. Utilizo disciplinas modernas como fq/fq_codel para regular el ritmo y la longitud de las colas con el fin de suavizar las ráfagas y evitar la saturación del búfer. En configuraciones con varias colas, combino esto con mqprio, para que las clases de tráfico permanezcan asignadas de forma coherente a las colas HW correctas. Junto con BQL (Byte Queue Limits) en el controlador reduce la latencia a plena carga porque la cola no crece de forma incontrolada.
Es importante interactuar con XPS en la ruta TX: Asigno las colas de envío a los núcleos en los que también aterrizan los flujos de recepción asociados. De este modo, ambas direcciones de un flujo permanecen cerca de la CPU y consigo tiempos de respuesta más estables con protocolos bidireccionales (por ejemplo, HTTP/2, gRPC).
Flujo de trabajo práctico en Linux
Empiezo con un registro de carga, compruebo la distribución de la CPU en top/htop, miro /proc/interrupts y /proc/softirqs y leo las estadísticas de ethtool para reconocer los cuellos de botella y preparar el siguiente Flujo de trabajo-paso. A continuación, determino los ID de IRQ de las colas de NIC relevantes y establezco máscaras de CPU adecuadas que ocupen los núcleos de manera uniforme y tengan en cuenta NUMA. A continuación, fijo los trabajadores de la aplicación a través de taskset o systemd-CPUAffinity a los mismos núcleos que también sirven a las colas asociadas. Sólo activo RPS/RFS cuando refuerza la localidad de flujo y mantengo la configuración coherente por interfaz. Por último, vuelvo a medir el rendimiento, la latencia y el jitter antes de implementar los cambios de manera uniforme en varios hosts.
Medición, evitar p95/p99 y regresiones
No me baso en intuiciones, sino que mido las latencias, las tasas de error y la utilización de los núcleos antes y después de cada ronda de ajuste, de modo que p99 permanece estable. También hago un seguimiento de los cambios de contexto, las tasas de migración y la carga por tipo de SoftIRQ para identificar efectos secundarios ocultos desde el principio. Mantengo la reproducibilidad de las pruebas, utilizo los mismos conjuntos de datos y versiones fijas para que los resultados sigan siendo comparables. Descubro regresiones con comprobaciones cruzadas en condiciones de pico y de reposo, así como con ejecuciones de larga duración. Sólo cuando las métricas, los registros y las trazas de la aplicación coinciden, declaro la configuración como nuevo estado de referencia.
Virtualización, contenedores y SR-IOV
En entornos virtualizados, me aseguro de que vCPU, La memoria y las vNIC de la VM se encuentran en el mismo nodo NUMA en el que termina la NIC física asociada. En la medida de lo posible, utilizo SR-IOV, para que la ruta de datos sea corta y las IRQ puedan vincularse directamente a los núcleos invitados. Conecto las vCPU de las máquinas virtuales críticas a los núcleos dedicados del host y me aseguro de que las IRQ del host y las IRQ del huésped no se solapen. En las configuraciones de contenedor, establezco cpusets y clases de QoS „garantizadas“ para que los contenedores de trabajadores y sus IRQ de red reciban tiempo de CPU de forma predecible.
Compruebo si irqbalance debe tener el liderazgo en el huésped o en el host - de lo contrario doble „automático“ produce desenfoque. Con virtio, establezco varias colas y las mapeo limpiamente a vCPUs para permitir el trabajo en paralelo. Si vhost-net utiliza núcleos de host individuales, redistribuyo los backends y mantengo los hilos vhost NUMA-cerca de la NIC física.
Solución de problemas: reconocer patrones rápidamente
- Núcleos saturados, ksoftirqd activo: Acerque más las colas de RX, compruebe el número de colas, ajuste RPS/RFS o aumente ligeramente la coalescencia.
- Nerviosismo en p99: Compruebe la deriva NUMA, verifique C-States/Governor, ajuste las descargas y los tamaños GRO paso a paso.
- Muchas retransmisiones/caídas: Compruebe los tamaños de los anillos RX/TX, qdisc y BQL, compruebe la coherencia de la tabla de indirección y XPS.
- Flujos desigualmente distribuidos: Equilibrar el hash RSS y la tabla de indirecciones, considerar la fijación de flujo caliente, mantener estable la semilla hash.
- Problema exclusivo de las máquinas virtuales: Colocar los backends vhost/virtio cerca de NUMA, evaluar SR-IOV, desagregar IRQs entre host y guest.
Incluir aplicaciones y bases de datos
Una ruta de red limpia no sirve de mucho si los servidores de aplicaciones o las bases de datos no funcionan en paralelo, por eso configuré la función Trabajador-número, thread pools y límites de conexión a los núcleos disponibles. Asigno los trabajadores de NGINX o HAProxy a los núcleos apropiados para que coincidan con las colas de RX. Escalo PHP-FPM, Node.js, Java o Go para que favorezcan el dominio NUMA local y utilicen múltiples instancias si es necesario. Integro cachés como Redis o Memcached cerca de la CPU y presto atención a sus propios parámetros de red e hilos. Solo la interacción de la afinidad IRQ, el anclaje de procesos y el escalado de aplicaciones proporciona un notable aumento de la latencia y el rendimiento.
Escenarios de alojamiento con grandes beneficios
Principalmente invierto en el ajuste profundo cuando las API generan muchas peticiones cortas o cuando En tiempo real-comunicaciones como VoIP y chats requieren valores de jitter bajos. Las configuraciones de comercio electrónico con picos de carga se benefician porque los flujos de pago son sensibles a la latencia. Los hosts multiinquilino con alta densidad se benefician porque los núcleos dedicados por cola reducen los efectos de vecindad. Los servicios de streaming también pueden conseguir más caudal por euro sin necesidad de adquirir inmediatamente nuevo hardware. Los costes siguen siendo calculables siempre que mantenga los cambios medibles y los despliegue con precisión.
Tabla de referencia rápida: núcleos, colas, herramientas
Utilizo lo siguiente Cuadro como recordatorio cuando configuro nuevos hosts o recalibro configuraciones existentes. Muestra objetivos típicos, medidas apropiadas, herramientas comunes de Linux y el efecto previsto sobre la latencia y el rendimiento. No lo uso dogmáticamente, sino como punto de partida para series de mediciones con tráfico real. Si varía la arquitectura NIC o la topología NUMA, adapto la selección de núcleos. Sigue siendo importante conservar la documentación para cada host y mantener la trazabilidad de los cambios.
| Objetivo | Medida | Herramienta/ubicación Linux | Efecto esperado |
|---|---|---|---|
| Distribuir la carga IRQ | Vincular claves a núcleos | /proc/irq/*/smp_affinity | Menos puntos calientes, latencia más constante |
| Aumentar la localidad de flujo | Ajustar CPU RPS/RFS | /sys/class/net/*/queues/*/rps_cpus | Menos migraciones, mejores cachés |
| Controlar el procesamiento por lotes | Ajuste de NAPI/coalescencia | ethtool -C / driver por defecto | Menor sobrecarga, jitter controlado |
| Emparejar app e IRQ | Pin trabajador | taskset, systemd CPUAffinity | Camino más corto, p99 más bajo |
| Evite NUMA | Co-localizar dispositivos y núcleos | numactl, lscpu, lspci -vv | Menos acceso remoto, más rendimiento |
Buenas prácticas que funcionan a largo plazo
Sólo cambio una palanca de control por ronda de pruebas, documento las métricas y guardo los resultados. Documentación en el repositorio del host. Mantengo la coherencia de las configuraciones describiendo claramente las asignaciones de cola a núcleo y utilizando secuencias de comandos para la replicación. Superviso los registros de caídas, retransmisiones y tiempos de espera y los correlaciono con las métricas del núcleo. Incluyo el hipervisor y el nivel de almacenamiento en el análisis para que no queden cuellos de botella en la sombra. Tengo preparadas reversiones en caso de que las pruebas muestren efectos negativos o cambien las cargas de trabajo.
Brevemente resumido
Consigo el máximo rendimiento de la red utilizando interrupciones, Cues y trabajadores y mantener así estable la ruta de datos por flujo. IRQ Affinity distribuye la carga de hardware de forma razonable, mientras que SoftIRQs, NAPI y RPS/RFS hacen que el procesamiento sea eficiente. La proximidad NUMA protege contra desvíos de memoria evitables y reduce el jitter. El ajuste paso a paso con mediciones reproducibles evita errores de configuración y muestra el progreso real. Si piensa en estos bloques de construcción de forma conjunta, podrá utilizar con confianza las capacidades de los modernos servidores multinúcleo para servicios de latencia crítica.


