Servidor web de almacenamiento en caché de 10/20 / 40Gbps nginx [20Gbps]


10

En esta pregunta, me gustaría encontrar la mejor configuración / hardware posible para entregar 40 Gbps desde un único servidor.

Situación

Tenemos un servidor proxy de video compartido que descarga picos de servidores de almacenamiento lento detrás de él. Todo el tráfico es solo HTTP. El servidor actúa como un proxy inverso (archivos que no están en caché en el servidor) y un servidor web (archivos que se almacenan en unidades locales).

Actualmente hay algo así como 100 TB de archivos y creciendo en los servidores de almacenamiento de fondo.

El mecanismo de almacenamiento en caché se implementa de forma independiente y esta pregunta no trata sobre el almacenamiento en caché en sí mismo, ya que funciona muy bien: actualmente ofrece 14 Gbps, pasa a los servidores de backend solo 2 Gbps. Entonces el uso de caché es bueno.

Objetivo

Logre 40 Gbps o incluso más rendimiento de una sola máquina.

Hardware 1

HW: Supermicro SC825, X11SSL-F, Xeon E3-1230v5 (4C/8T@3.4GHz), 16GB DDR4 RAM, 2x Supermicro 10G STGN-i1S (LACP L3 + 4)

SSD: 1x 512GB Samsung, 2x 500GB Samsung, 2x480GB Intel 535, 1x 240GB Intel S3500

Sistema:

  • irqbalancer se detuvo
  • set_irq_affinity para cada interfaz (a través de un script en el tarball del controlador ixgbe)
  • ixgbe-4.3.15
  • Fecha límite de planificador de E / S
  • iptables empty (módulos descargados)
  • Sistema de archivos: XFS

Nginx:

  • enviar archivo
  • hilos aio
  • directio 1M
  • tcp_nopush en
  • tcp_nodelay on

ingrese la descripción de la imagen aquí ingrese la descripción de la imagen aquí ingrese la descripción de la imagen aquí

Como se ve en los gráficos, pudimos impulsar 12.5Gbps. Lamentablemente, el servidor no respondió.

Hay 2 cosas que me llamaron la atención. El primero es una gran cantidad de IRQ. En este caso, desafortunadamente no tengo gráficos de / proc / interrupts. Lo segundo fue la alta carga del sistema, que creo que fue causada por que kswapd0 tuvo problemas para trabajar solo con 16G de RAM.

Hardware 2

HW: Supermicro SC119TQ, X10DRW-i, 2x Xeon E5-2609v4 (8C/8T@1.70GHz), 128GB DDR4 RAM, 2x Supermicro 10G STGN-i1S

SSD, la configuración del sistema es la misma que la del hardware 1. Nginx tiene sendfile activado (aio / sendfile en comparación adicional).

ingrese la descripción de la imagen aquí ingrese la descripción de la imagen aquí ingrese la descripción de la imagen aquí

Esto parece mejor, así que ahora que tenemos un servidor, que funciona en picos, podemos probar algunas optimizaciones.

Sendfile vs hilos aio

Traté de desactivar sendfile y usar hilos aio en su lugar.

  • enviar archivo
  • hilos aio
  • directio 1M (que coincide con todos los archivos que tenemos)

vs

  • enviar en

Luego, a las 15:00, volví a enviar archivos y volví a cargar nginx (por lo que me tomó un tiempo terminar las conexiones existentes). Es bueno que la utilización de la unidad (medida por iostat) haya disminuido. Nada ha cambiado en el tráfico (desafortunadamente zabbix decidió no recopilar los datos de bond0).

ingrese la descripción de la imagen aquí ingrese la descripción de la imagen aquí ingrese la descripción de la imagen aquí

sendfile activado / desactivado

Solo intenté activar / desactivar el envío. Nada ha cambiado excepto reprogramar interrupciones.

ingrese la descripción de la imagen aquí ingrese la descripción de la imagen aquí

irqbalancer como servidor / cron / deshabilitado

Como @lsd mencionó, intenté configurar irqbalancer para que se ejecute a través de cron:

*/5 * * * *   root    /usr/sbin/irqbalance --oneshot --debug 3 > /dev/null

Lamentablemente no ayudó en mi caso. Una de las tarjetas de red comenzó a comportarse de manera extraña:

ingrese la descripción de la imagen aquí

No pude encontrar lo que estaba mal en los gráficos y, como sucedió al día siguiente nuevamente, inicié sesión en el servidor y vi que un núcleo estaba al 100% (uso del sistema).

Traté de iniciar irqbalance como un servicio, el resultado seguía siendo el mismo.

Luego decidí usar el script set_irq_affinity y solucionó el problema de inmediato y el servidor presionó 17Gbps nuevamente.

Hardware 3

Actualizamos al nuevo hardware: 2U 24 (+2) unidades de chasis (6xSFF), 2x Xeon E5-2620v4, 64GB DDR4 RAM (módulos de 4x16GB), 13x SSD, 2x tarjetas de red Supermicro (con chip Intel). Las nuevas CPU mejoraron mucho el rendimiento.

La configuración actual permanece: sendfile, etc. La única diferencia es que solo dejamos que una sola CPU maneje ambas tarjetas de red (a través del script set_irq_affinity).

Se ha alcanzado el límite de 20 Gbps.

ingrese la descripción de la imagen aquí ingrese la descripción de la imagen aquí

¿Próximo objetivo? 30 Gbps.


Siéntase libre de enviarme ideas sobre cómo mejorar el rendimiento. Estaré encantado de probarlo en vivo y compartir algunos gráficos pesados ​​aquí.

¿Alguna idea de cómo lidiar con una gran cantidad de SoftIRQ en la CPU?

Esta no es una pregunta sobre la planificación de la capacidad: ya tengo el hardware y el tráfico. Siempre puedo dividir el tráfico en varios servidores (lo que tendré que hacer en el futuro de todos modos) y solucionar el problema con dinero. Sin embargo, esta es una pregunta sobre la optimización del sistema y el ajuste del rendimiento en un escenario real en vivo.



44
Usted dice que esto no se trata de planificación de capacidad, pero me parece que intentar empujar 40 Gbps a través de un solo servidor es indicativo de problemas de capacidad.
ceejayoz 01 de

55
Solo un comentario interesante, en un trabajo anterior, desactivaron el servicio de irqbalance, pero aún ejecutaban un trabajo cron que ejecutaba irqbalance cada 15 minutos más o menos. Así que todavía tenemos ventaja de irqbalance, solo que no con la frecuencia del servicio.
lsd

Actualización: se agregó la prueba de activación / desactivación de sendfile. @lsd: Intentaré usar irqbalance como independiente vía cron la próxima semana. Veamos cuál será el impacto.
Yarik Dot

1
¿Qué usaste para hacer los gráficos?
Johnny V

Respuestas:


9

Descargo de responsabilidad : el mismo consejo se aplica a todos los servicios que generan más de 10 Gbps. Se incluyen, entre otros, equilibradores de carga, servidores de almacenamiento en caché, servidores web (HAProxy, Varnish, nginx, tomcat, ...)

Lo que quieres hacer está mal, no lo hagas

Use un CDN en su lugar

CDN está destinado a entregar contenido estático en caché. Use la herramienta adecuada para el trabajo (akamai, MaxCDN, cloudflare, cloudfront, ...)

Cualquier CDN, incluso uno gratuito, funcionará mejor que cualquier cosa que pueda lograr por su cuenta.

Escala horizontalmente en su lugar

Espero que un solo servidor maneje 1-5Gbps fuera de la caja sin muchos ajustes (nota: solo sirve archivos estáticos). Los 8-10 Gbps generalmente están al alcance con una afinación avanzada.

Sin embargo, hay muchos límites duros para lo que puede tomar una sola caja. Debes preferir escalar horizontalmente.

Ejecute una sola caja, pruebe cosas, mida, compare, optimice ... hasta que esa caja sea confiable y confiable y sus capacidades estén bien determinadas, luego coloque más cajas como esta con un balanceador de carga global al frente.

Hay algunas opciones de equilibrio de carga global: la mayoría de CDN puede hacer eso, DNS roundrobin, ELB / Google balanceadores de carga ...

Ignoremos las buenas prácticas y hagámoslo de todos modos

Comprender el patrón de tráfico

            WITHOUT REVERSE PROXY

[request ]  user ===(rx)==> backend application
[response]  user <==(tx)===     [processing...]

Hay dos cosas a considerar: el ancho de banda y la dirección (emisión o recepción).

Los archivos pequeños son 50/50 tx / rx porque los encabezados HTTP y la sobrecarga TCP son más grandes que el contenido del archivo.

Los archivos grandes son 90/10 tx / rx porque el tamaño de la solicitud es insignificante en comparación con el tamaño de la respuesta.

            WITH REVERSE PROXY

[request ]  user ===(rx)==> nginx ===(tx)==> backend application
[response]  user <==(tx)=== nginx <==(rx)===     [processing...]

El proxy inverso está retransmitiendo todos los mensajes en ambas direcciones. La carga siempre es 50/50 y el tráfico total se duplica.

Se vuelve más complejo con el almacenamiento en caché habilitado. Las solicitudes pueden desviarse al disco duro, cuyos datos pueden almacenarse en la memoria caché.

Nota : Ignoraré el aspecto de almacenamiento en caché en esta publicación. Nos centraremos en obtener 10-40 Gbps en la red. Saber si los datos provienen de la memoria caché y optimizar esa memoria caché es otro tema, se transfiere por el cable de cualquier manera.

Limitaciones de monocore

El equilibrio de carga es monocore (especialmente el equilibrio TCP). Agregar núcleos no lo hace más rápido, pero puede hacerlo más lento.

Lo mismo para el equilibrio HTTP con modos simples (por ejemplo, IP, URL, basado en cookies. El proxy inverso lee los encabezados sobre la marcha, no analiza ni procesa las solicitudes HTTP en sentido estricto).

En el modo HTTPS, el descifrado / cifrado SSL es más intensivo que todo lo demás requerido para el proxy. El tráfico SSL puede y debe dividirse en múltiples núcleos.

SSL

Dado que haces todo a través de SSL. Querrás optimizar esa parte.

Cifrar y descifrar 40 Gbps sobre la marcha es todo un logro.

Tome un procesador de última generación con las instrucciones AES-NI (utilizado para operaciones SSL).

Ajuste el algoritmo utilizado por los certificados. Hay muchos algoritmos Desea el que sea más efectivo en su CPU (realice una evaluación comparativa) MIENTRAS que sea compatible con los clientes Y sea lo suficientemente seguro (no es necesario un cifrado excesivo).

IRQ y fijación de núcleos

La tarjeta de red genera interrupciones (IRQ) cuando hay nuevos datos para leer y la CPU se adelanta para manejar la cola de inmediato. Es una operación que se ejecuta en el kernel y / o los controladores del dispositivo y es estrictamente monocore.

Puede ser el mayor consumidor de CPU con miles de millones de paquetes que salen en todas las direcciones.

Asigne a la tarjeta de red un número IRQ único y fíjelo a un núcleo específico (consulte la configuración de Linux o BIOS).

Ancla el proxy inverso a otros núcleos. No queremos que estas dos cosas interfieran.

Adaptador de Ethernet

La tarjeta de red está haciendo mucho trabajo pesado. Todos los dispositivos y fabricantes no son iguales en lo que respecta al rendimiento.

Olvídate del adaptador integrado en las placas base (no importa si la placa base del servidor o del consumidor), simplemente apestan.

Descarga de TCP

TCP es un protocolo muy intensivo en términos de procesamiento (sumas de verificación, ACK, retransmisión, reensamblado de paquetes, ...) El núcleo maneja la mayor parte del trabajo, pero algunas operaciones pueden descargarse a la tarjeta de red si lo admite.

No queremos solo una tarjeta relativamente rápida , queremos una con todas las campanas y silbatos.

Olvídate de Intel, Mellanox, Dell, HP, lo que sea. No apoyan todo eso.

Solo hay una opción sobre la mesa: SolarFlare : el arma secreta de las empresas HFT y CDN.

El mundo está dividido en dos tipos de personas: " Los que conocen SolarFlare " y " los que no ". (el primer conjunto es estrictamente equivalente a " personas que hacen redes de 10 Gbps y se preocupan por cada bit "). Pero me estoy desviando, centrémonos: D

Kernel TCP tuning

Hay opciones sysctl.confpara los buffers de red del kernel. Qué hacen o no estas configuraciones. Realmente no lo sé.

net.core.wmem_max
net.core.rmem_max
net.core.wmem_default
net.core.rmem_default

net.ipv4.tcp_mem
net.ipv4.tcp_wmem
net.ipv4.tcp_rmem

Jugar con estos ajustes es el signo definitivo de una optimización excesiva (es decir, generalmente inútil o contraproducente).

Excepcionalmente, eso podría tener sentido dados los requisitos extremos.

(Nota: 40 Gbps en una sola caja es una optimización excesiva. La ruta razonable es escalar horizontalmente).

Algunos límites físicos

Ancho de banda de memoria

Algunos números sobre el ancho de banda de la memoria (principalmente en GB / s): http://www.tweaktown.com/articles/6619/crucial-ddr4-memory-performance-overview-early-look-vs-ddr2-ddr3/index.html

Digamos que el rango es de 150-300 Gbps para el ancho de banda de la memoria (límite máximo en condiciones ideales).

Todos los paquetes tienen que estar en la memoria en algún momento. Simplemente ingerir datos a una velocidad de línea de 40 Gbps es una carga pesada en el sistema.

¿Quedará algún poder para procesar los datos? Bueno, no tengamos nuestras expectativas demasiado altas en eso. Solo digo ^^

Bus PCI-Express

PCIe 2.0 es de 4 Gb / s por carril. PCIe 3.0 es de 8 Gbps por carril (no todo está disponible para la tarjeta PCI).

Una NIC de 40 Gbps con un solo puerto Ethernet promete más que el bus PCIe si el conector tiene menos de 16x de longitud en las especificaciones v3.0.

Otro

Podríamos superar otros límites. El punto es que el hardware tiene limitaciones difíciles inherentes a la ley de la física.

El software no puede hacerlo mejor que el hardware en el que se está ejecutando.

La red troncal de la red

Todos estos paquetes tienen que ir a algún lugar eventualmente, atravesando conmutadores y enrutadores. Los conmutadores y enrutadores de 10 Gbps son [casi] una mercancía. Los 40 Gbps definitivamente no lo son.

Además, el ancho de banda tiene que ser de extremo a extremo, ¿qué tipo de enlaces tiene hasta el usuario?

La última vez que verifiqué con mi chico del centro de datos para un pequeño proyecto secundario de 10 millones de usuarios, me dejó bastante claro que solo habría enlaces de 2x 10 Gbits a Internet como máximo.

Unidades de disco duro

iostat -xtc 3

Las métricas se dividen en lectura y escritura. Compruebe la cola (<1 es buena), la latencia (<1 ms es buena) y la velocidad de transferencia (cuanto mayor sea, mejor).

Si el disco es lento, la solución es poner más SSD más grande en la incursión 10. (tenga en cuenta que el ancho de banda de SSD aumenta linealmente con el tamaño de SSD).

Elección de CPU

IRQ y otros cuellos de botella solo se ejecutan en un núcleo, por lo tanto, apunte a la CPU con el rendimiento de núcleo único más alto (es decir, la frecuencia más alta).

El cifrado / descifrado SSL necesita las instrucciones AES-NI, por lo tanto, apunte a la última revisión de la CPU solamente.

El SSL se beneficia de múltiples núcleos, así que apunte a muchos núcleos

En pocas palabras: la CPU ideal es la más nueva con la frecuencia más alta disponible y muchos núcleos. Simplemente elija el más caro y probablemente sea eso: D

enviar archivo()

Sendfile ON

Simplemente el mayor progreso de los núcleos modernos para servidores web de alto rendimiento.

Nota final

1 SolarFlare NIC 40 Gbps (pin IRQ and core)
2 SolarFlare NIC 40 Gbps (pin IRQ and core)
3 nginx master process
4 nginx worker
5 nginx worker
6 nginx worker
7 nginx worker
8 nginx worker
...

Una cosa anclada a una CPU. Ese es el camino a seguir.

Una NIC que conduce al mundo externo. Una NIC que conduce a la red interna. Dividir las responsabilidades siempre es bueno (aunque la NIC dual de 40 Gbps puede ser exagerada).

Eso es un montón de cosas para afinar, algunas de las cuales podrían ser el tema de un pequeño libro. Diviértete comparando todo eso. Vuelve a publicar los resultados.


Las tarjetas de red Solarflare se han ordenado hace unas semanas para realizar pruebas. Ahora espero avisa al soporte de Solarflare sobre cómo ajustar el sistema para obtener el máximo. posible rendimiento Después de esta prueba, compartiré la configuración y los resultados.
Yarik Dot

1
Standing Ovation ....
James Pulley

Solo una actualización rápida en los discos duros: el uso de cualquier tipo de incursión en este escenario (unidades ssd) no funciona correctamente. Como los SSD se usan de manera diferente, tienen un rendimiento diferente y con un SSD lento en la incursión, el rendimiento completo de la incursión puede ser pobre. El mejor escenario, que nos funciona mejor, es usar unidades individuales, sin ninguna incursión HW / SW.
Yarik Dot

0

Todavía no puedo comentar debido a la reputación, así que tengo que agregar una respuesta en su lugar ...

En el primer ejemplo, dijiste:

Hay 2 cosas que me llamaron la atención. El primero es una gran cantidad de IRQ. En este caso, desafortunadamente no tengo gráficos de / proc / interrupts. Lo segundo fue la alta carga del sistema, que creo que fue causada por que kswapd0 tuvo problemas para trabajar solo con 16G de RAM.

Absolutamente de acuerdo en que estos son puntos importantes.

  1. Intente usar el agente collectd, que puede recopilar IRQ y almacenar utilizando RRD.

  2. ¿Tienes una tabla de uso de memoria?

    Mientras que en la superficie, esto parece un problema de la CPU, el alto porcentaje de softirq podría simplemente señalar con el dedo a la memoria, si hay muchas fallas de página duras o suaves. Creo que el obsequio es la escalada repentina en los IRQ, a expensas de la CPU del sistema aproximadamente a las 19:00.

Por lo que puedo ver en las especificaciones, todo se ve igual excepto:

  • la memoria
  • los modelos de CPU: a menos que me equivoque, los puntos de referencia indicarían que deberían ser similares, y en este tipo de casos preferiría la caja con menos núcleos más rápidos.
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.