BLOG | NGINX

Módulo de gestión de API del controlador NGINX vs. Kong: Comparación de rendimiento

NGINX - Parte de F5 - horizontal, negro, tipo RGB
Miniatura de Faisal Memon
Faisal Memon
Publicado el 6 de mayo de 2019

El mercado de gestión de API (APIM) es un espacio abarrotado. El último Cuadrante Mágico de Gartner para la gestión de API de ciclo de vida completo clasifica a 22 proveedores, 7 de ellos en el cuadrante de líderes. Competir en un mercado existente requiere establecer una posición sólida para diferenciarse y destacarse de la competencia. Entonces, ¿qué hace que la solución de gestión de API de NGINX sea diferente?

En NGINX nuestro objetivo es crear software liviano y de alto rendimiento. NGINX Open Source se ha convertido en el servidor web de referencia para los sitios más activos del mundo porque su arquitectura basada en eventos escala mejor que los servidores web que generan un proceso o hilo para cada conexión. NGINX Open Source es también la puerta de enlace API más omnipresente de la industria, un componente de infraestructura que procesa el tráfico de API en soluciones APIM como las de Apigee, Axway, IBM DataPower, Kong, Red Hat 3scale y Torry Harris.

El módulo de gestión de API del controlador NGINX es una solución APIM de alto rendimiento. En este blog compararemos su rendimiento con el de Kong, un competidor conocido por su alto rendimiento. Kong está construido sobre NGINX y utiliza Lua para implementar su funcionalidad API, mientras que el módulo de administración de API se basa completamente en capacidades nativas de alto rendimiento que se implementan como módulos NGINX Plus. La solución de gestión de API de NGINX está construida sobre una arquitectura innovadora que desacopla el plano de datos y el plano de control. Todas las llamadas API son manejadas directamente por NGINX Plus, actuando como puerta de enlace API (plano de datos) sin requerir ninguna interacción con el plano de control. Esto da como resultado una mediación de tráfico API de alto rendimiento tanto para el tráfico norte-sur como para el este-oeste.

Un adelanto de los resultados: el módulo de gestión de API del controlador NGINX supera a Kong en 2x.

Un agradecimiento especial a Intel por proporcionar el hardware y el espacio de laboratorio utilizados para realizar estas pruebas. Los detalles completos de las pruebas y del hardware se pueden encontrar en el Apéndice .

Latencia añadida a una sola solicitud

En esta prueba comparamos la latencia adicional introducida por el administrador de API en una sola solicitud, para archivos de 0 KB y 1 KB de tamaño. Usamos curl para enviar la única solicitud HTTP ( detalles ).

Kong aumenta la latencia en comparación con el módulo de gestión de API: en un 44 % para un archivo de 0 KB y en un 24 % para un archivo de 1 KB.

Llamadas API por segundo

Una métrica de escalabilidad HTTP estándar son las solicitudes por segundo (RPS). La métrica equivalente en el contexto de APIM son las llamadas API por segundo. Usamos wrk para enviar un flujo continuo de solicitudes de archivos de 0 KB o 1 KB , en 300 conexiones durante 3 minutos ( detalles ).

El módulo de administración de API superó a Kong: manejó 2,6 veces más llamadas de API por segundo para respuestas de 1 KB .

Uso de CPU

El módulo de administración de API introduce menos latencia y maneja más llamadas de API por segundo que Kong porque utiliza la CPU de manera más eficiente. Medimos el uso de la CPU en cantidades crecientes de llamadas API por segundo. Utilizamos un solo núcleo, por lo que el número absoluto de llamadas API por segundo es mucho menor que en la prueba anterior, donde utilizamos 22 núcleos ( detalles ).

Kong efectivamente tiene un límite de 5000 llamadas API por segundo: la latencia aumenta notablemente con volúmenes de llamadas superiores a ese, lo que indica que el sistema está completamente cargado. Con 5000 llamadas por segundo, el uso de la CPU es del 93 %, un 73 % más alto que el módulo de administración de API.

Llamadas API por segundo con JWT

La prueba final mide qué tan bien cada puerta de enlace API valida los tokens web JSON (JWT), el método preferido para autenticar solicitudes de API. Es probable que sus puntos finales de API más importantes estén autenticados, por lo que esta prueba se aproxima más a una configuración del mundo real.

Utilizamos el mismo JWT, firmado con HS256, con ambas pasarelas ( detalles ).

El módulo de administración de API maneja más del doble de llamadas API autenticadas mediante JWT por segundo que Kong.

Cómo funciona el controlador NGINX

NGINX Controller es una solución de plano de control que administra el plano de datos NGINX Plus. El controlador NGINX le permite administrar todo el ciclo de vida de NGINX Plus, como un balanceador de carga, una puerta de enlace API o un proxy en un entorno de malla de servicios. Con el módulo de gestión de API del controlador NGINX, puede definir, publicar, proteger, supervisar y analizar API.

Bajo el capó, NGINX Controller genera la configuración de NGINX Plus que se publica en el plano de datos NGINX Plus subyacente. El cargador de configuración principal tiene un mecanismo muy eficiente para almacenar configuraciones en la memoria, lo que permite que el módulo de administración de API ofrezca un alto rendimiento para las API.

CONCLUSIÓN

Muchas empresas ya utilizan NGINX Open Source como su puerta de enlace API. Capital One ha podido escalar a más de 12 mil millones de llamadas API por día utilizando NGINX Open Source. De hecho, muchos de nuestros competidores, incluido Kong, utilizan NGINX Open Source en sus soluciones APIM. Nuestro diseño liviano, basado en la configuración nativa de NGINX de alto rendimiento junto con los módulos NGINX Plus, permite que el módulo de administración de API se escale mejor que la competencia derivada de NGINX.

La latencia es una de las métricas más importantes para la experiencia del usuario final. La alta latencia reduce la capacidad de respuesta de la aplicación, frustrando a los usuarios. El módulo de gestión de API agrega entre un 20 % y un 30 % menos de latencia a las solicitudes de los usuarios en comparación con Kong. También utiliza los recursos del sistema de manera más eficiente, utilizando un 40% menos de CPU que Kong para la misma carga de trabajo.


Anexo

Topología

Todas las pruebas se realizaron utilizando tres máquinas separadas conectadas por enlaces de 10 GbE en una red de capa 2 simple y plana.

Hardware usado

Para la prueba se utilizó el siguiente hardware. Las tres máquinas eran idénticas. No se utilizó hyperthreading. En pruebas anteriores no observamos una diferencia importante en el rendimiento del hyperthreading.

CPU Red Memoria
CPU Intel® Xeon(R) E5‑2699 v4 a 2,20 GHz, 22 núcleos Controlador Ethernet Intel 10‑Gigabit X540‑AT2 128 GB

Software utilizado

Para realizar las pruebas se utilizó el siguiente software:

  • Módulo de gestión de API del controlador NGINX versión 2.
  • Kong versión de código abierto 1.0.0. No probamos Kong Enterprise, pero ninguna de sus características adicionales es relevante para nuestras pruebas (por ejemplo, Kong Open Source y Kong Enterprise usan el mismo complemento JWT).
  • curl versión 7.61.0.
  • Versión de Docker 18.09.1. Para facilitar la gestión, ejecutamos Kong y el módulo de gestión de API dentro de contenedores Docker. Descubrimos que Docker reduce el rendimiento en aproximadamente un 30 %, pero como estamos comparando el rendimiento relativo, los beneficios de usar Docker superaron el impacto en el rendimiento.
  • mpstat en la versión 12.0.1 del paquete systat .
  • wrk versión 4.1.0, instalada según estas instrucciones .

Configuración de NGINX

Se utilizó la siguiente configuración de NGINX para la prueba.

upstream my_upstream { keepalive 60; servidor API-server :80; keepalive_requests 3000000; keepalive_timeout 300; } servidor { escuchar 8000; acceso_cerrar sesión; keepalive_requests 3000000; keepalive_timeout 300; tcp_nodelay activado; ubicación /prueba { establecer $apimgmt_environment 4; establecer $apimgmt_definition 3; establecer $upstream my_upstream; establecer $upstream_protocol http; reescribir ^ /_devel_4 último; } ubicación = /_devel_4 { interno; establecer $apimgmt_definition_name my_api; establecer $apimgmt_environment_name devel; proxy_intercept_errors activado; proxy_http_version 1.1; proxy_set_header Conexión ""; proxy_pass $upstream_protocol://$upstream/0kb; # archivo de 0 KB #proxy_pass $upstream_protocol://$upstream/1kb.bin; # archivo de 1 KB } }

Realizamos las siguientes configuraciones para maximizar el rendimiento. Como se detalla en la siguiente sección, realizamos configuraciones similares en la configuración de Kong.

  • keepalive_requests y keepalive_timeout se establecieron en un número alto para minimizar la sobrecarga derivada de la configuración de conexiones TCP.
  • Se habilitó tcp_nodelay , mejorando levemente el rendimiento al deshabilitar el algoritmo de Nagle.
  • access_log fue deshabilitado. Habilitarlo reduce el rendimiento en aproximadamente un 10%.
  • Utilizamos las dos directivas proxy_pass para solicitar el tamaño de archivo apropiado.

Configuración de Kong

Agregamos las siguientes directivas de configuración a kong.conf.default , que coinciden con las configuraciones de la configuración de NGINX analizada en la sección anterior.

Retardo de nodo TCP de nginx_http=activado Solicitudes de mantenimiento de nginx_http=3000000
Tiempo de espera de mantenimiento de nginx_http=300
Registro de acceso al proxy=desactivado

Ejecutamos las siguientes llamadas a la API de Kong para crear una ruta al servidor API. El primer comando crea un servicio llamado test y el segundo crea la ruta /test que apunta al servidor.

$ curl -X POST http://localhost:8001/servicios/ \ --data 'nombre=prueba' \ --data 'url=http:// API-servidor :80/0kb' $ curl -X POST http://localhost:8001/servicios/prueba/rutas \ --data 'rutas[]=/prueba'

Los siguientes comandos muestran la configuración del servicio y la ruta, respectivamente. Canalizamos la salida a la herramienta jq para facilitar la lectura de la salida JSON.

$ curl localhost:8001/servicios/ | jq '.' { "siguiente": null, "datos": [ { "host": "172.20.40.32", "creado_en": 1556770191, "tiempo de espera de conexión": 60000, "id": "f4629d56-550b-4b37-aa59-66d931aa6f37", "protocolo": "http", "nombre": "prueba", "tiempo de espera de lectura": 60000, "puerto": 80, "ruta": "/0kb", "actualizado_en": 1556770191, "reintentos": 5, "tiempo de espera de escritura": 60000 } ] } $ curl localhost:8001/servicios/prueba/rutas | jq '.' { "siguiente": null, "datos": [ { "creado_en": 1556770191, "métodos": nulo, "id": "a7b417af-ccd4-48f7-b787-ae19490194dc", "servicio": { "id": "f4629d56-550b-4b37-aa59-66d931aa6f37" }, "nombre": nulo, "hosts": nulo, "actualizado_en": 1556770191, "preserve_host": falso, "regex_priority": 0, "rutas": [ "/prueba" ], "orígenes": nulo, "destinos": nulo, "snis": nulo, "protocolos": [ "http", "https" ], "strip_path": verdadero } ] }

Metodología de pruebas

Latencia añadida a una sola solicitud

Utilizamos curl para la prueba de latencia de solicitud única. Para establecer una línea base, primero hicimos una solicitud al servidor API sin una puerta de enlace API delante. Luego hicimos la misma solicitud con cada puerta de enlace API frente al servidor API para medir la latencia que introdujeron.

$ curl -w "@curl-latency.txt" -o /dev/null -s http:// servidor-destino

El contenido de curl-latency.txt :

    Búsqueda_de_nombre_tiempo: %{Búsqueda_de_nombre_tiempo}\n
Conexión_tiempo: %{Conexión_tiempo}\n
Conexión_aplicación_tiempo: %{Conexión_aplicación_tiempo}\n
Pretransferencia_tiempo: %{Pretransferencia_tiempo}\n
Redirección_tiempo: %{Redirección_tiempo}\n
Inicio_transferencia_tiempo: %{Inicio_transferencia_tiempo}\n
----------\n
Total_tiempo: %{Total_tiempo}\n

El gráfico de Latencia agregada a una sola solicitud muestra time_total , en milisegundos. A continuación se muestra un ejemplo de salida:

$ curl -w "@curl-latency.txt" -o /dev/null -s http://192.0.2.1/api-endpoint búsqueda_de_nombre_de_hora:  0.000035 tiempo_conexión:  0.000364 tiempo_appconnect:  0.000000 tiempo_pretransferencia:  0.000401 tiempo_redireccionamiento:  0.000000 tiempo_iniciar transferencia:  0.001701 ---------- tiempo_total:  0.001727

Llamadas API por segundo

Probamos las llamadas API por segundo con wrk , una herramienta de evaluación comparativa escalable que utilizamos a menudo. Probamos varias combinaciones de parámetros y esta maximizó el rendimiento tanto del módulo de administración de API como de Kong:

$ wrk -t 22 -c 300 -d 180 http:// servidor-de-destino

El comando crea 22 subprocesos wrk (1 por núcleo) y un total de 300 conexiones entre los subprocesos. El parámetro -d especifica la duración de la prueba, en nuestro caso 180 segundos (3 minutos). Ejemplo de salida:

$ wrk -t 22 -c 300 -d 180 http://192.0.2.1/api-endpoint Ejecutando prueba de 3 m en http://192.0.2.1/api-endpoint 22 subprocesos y 300 conexiones Estadísticas de subprocesos Desviación estándar promedio Desviación estándar máxima +/- Latencia 13,96 ms 7,84 ms 279,85 ms 77,37 % Solicitudes/seg 0,96 k 298,23 1,88 k 68,55 % 3769861 solicitudes en 3,00 m, 36,25 GB de lectura Solicitudes/seg:  20934.34 Transferencia/seg:    206,16 MB

Uso de CPU

Probamos el uso de la CPU con mpstat (una herramienta estándar de Linux para ese propósito) mientras ejecutábamos el comando wrk para llamadas API por segundo. Ejemplo de salida (distribuido en dos líneas para facilitar la legibilidad):

$ mpstat Linux 4.18.0-13-generic (nbdw38) 29/04/2019 _x86_64_ (88 CPU) 15:34:50 CPU %usr %nice %sys %iowait %irq %soft %steal ...
15:34:50 todos 0.04 0.00 0.02 0.00 0.00 0.03 0.00 ... ... %guest %gnice %idle ...   0.00    0.00   99.91

Llamadas API por segundo con JWT

Probamos el rendimiento de JWT con el comando wrk para llamadas API por segundo, con la adición del parámetro -H para insertar el JWT en la Autorización: Portador Encabezado HTTP. Generamos las claves web JWT y JSON (JWKs) siguiendo las instrucciones de esta publicación de blog y almacenamos las JWT en un archivo llamado test.jwt .

$ wrk -t 22 -c 300 -d 180 -H "Autorización: Portador `cat test.jwt`" \ http:// servidor-objetivo

"Esta publicación de blog puede hacer referencia a productos que ya no están disponibles o que ya no reciben soporte. Para obtener la información más actualizada sobre los productos y soluciones F5 NGINX disponibles, explore nuestra familia de productos NGINX . NGINX ahora es parte de F5. Todos los enlaces anteriores de NGINX.com redirigirán a contenido similar de NGINX en F5.com.