Desarrolladores, hagan explotar sus API 🧨

Este artículo sigue a una presentación realizada en Human Talks en septiembre de 2022. Las diapositivas están disponibles ici.

Durante mi misión en rca en 2021/2022, me uní a un equipo que trabajaba en API públicas disponibles detrás de un Administrador de API, gravitatorio. Esta plataforma permite, entre otras cosas, controlar y securizar nuestras APIs. Por ejemplo, el “límite de tasa” consiste en limitar el número de llamadas a una API en un intervalo de tiempo determinado.

A pesar de la implementación de esta protección, era importante para nosotros poder estimar el límite de uso de nuestra API y nuestra plataforma. Con la llegada de nuevos clientes, el uso de la API, y por tanto los incrementos de carga, serán progresivos.

El término “disparo de carga” puede definirse de diferentes formas dependiendo de los perfiles de personas o empresas.

Para nosotros, ejecutar disparos de carga se trata de simular una gran cantidad de llamadas a nuestra API en muy poco tiempo, con el objetivo de llegar a “explosión” nuestra API.


Gatling: nuestra primera prueba de carga

Para encontrar estos límites, recurrimos a la solución gatling. ¿Por qué no usar otras herramientas “más rápidas” como trabajaruna herramienta de línea de comandos que no afecta los desarrollos?

En RCA, el ecosistema de pruebas se construye con la API Kárateuna herramienta de prueba automatizada que pretende ser fácil de usar, ya seas un desarrollador o una persona menos técnica.

con el lenguaje Pepinillo, podremos escribir nuestros escenarios de prueba. Por ejemplo :

Feature: Guess the word
   # The first example has two steps
   Scenario: Maker starts a game
      When the Maker starts a game
      Then the Maker waits for a Breaker to join
Entrar en modo de pantalla completaSalir del modo de pantalla completa

Gatling puede reutilizar estos escenarios de Karate para ejecutar tiros de carga. Su integración en una API es muy sencilla. Solo obtén la dependencia karate-gatling :


    com.intuit.karate
    karate-gatling
    test

Entrar en modo de pantalla completaSalir del modo de pantalla completa

Cuando iniciamos este trabajo en torno a las pruebas de carga, solo DSL Scala estaba disponible. Desde entonces, se ha creado un DSL de Java.

class GatlingSimulation extends Simulation{
  val test = scenario("tirs-charge").exec(karateFeature("classpath:scenarios/charge/tirs-charge.feature"))
Entrar en modo de pantalla completaSalir del modo de pantalla completa

Después de crear un perfil Experto dedicado a estas pruebas de carga, el siguiente comando permite ejecutar nuestra clase GatlingSimulación: mvn clean test-compile gatling:test

Luego, Gatling genera un informe HTML que contiene información completa sobre la cantidad de solicitudes enviadas, los tiempos promedio de respuesta y los estados de las solicitudes, como se muestra en los siguientes informes:

Gatling de relación siguiente

Rápidamente, podemos ver en el primer gráfico que los indicadores parecen correctos a primera vista. La API respondió a las 3.000 solicitudes realizadas en un máximo de 800 milisegundos. Para una API y en vista de nuestra experiencia, este es un valor bastante razonable.

Esta tendencia se confirma en el gráfico de barras. Nuestra API respondió en 200 ms.

Los rangos de tiempo de respuesta, visibles en los gráficos (800ms, 1200ms) son valores base definidos por Gatling.


Integración | automatización en CI/CD

Una vez que se ha escrito el escenario de Gatling, es totalmente posible probarlo ejecutándolo en su propia estación de trabajo. Una toma de carga en una API implementada en su propia computadora también lo es. Pero, ¿cuál es el punto de hacer esta prueba localmente o desde su estación de trabajo? Cada toma dependerá de la potencia y capacidad de tu ordenador en ese momento. Si nuestro objetivo es encontrar límites a nuestra API, esto no dará como resultado un balance relevante.

Para tener resultados interpretables, implementamos nuestra API en una infraestructura “pruebas”, casi equivalente al de producción. Es un poco más pequeño.

Como se dijo antes, nuestro objetivo era darnos un límite de solicitud para que nuestra API tuviera tiempos de respuesta aceptables. Por lo tanto, la infraestructura que ejecutaba los escenarios de Karate tenía que ser lo suficientemente poderosa, lo que no es el caso de nuestras computadoras.

¿Cuál es el punto de tener que instalar herramientas como Maven para poder ejecutar un disparo de carga?

La interfaz de usuario bastante fácil de usar de GitLab permite que cualquier perfil active canalizaciones rápidamente. En RCA, el mecanismo que ejecuta las tuberías, Corredor de GitLabestá instalado sobre una potente infraestructura.

Hemos creado un nuevo puesto de trabajo”🧯carga tomas en prueba 🔥” en nuestra canalización de GitLab existente para hacer posible ejecutar un tiro de carga en nuestra API implementada en el entorno iso de producción.

Pipeline GitLab CI


Los problemas encontrados (y soluciones)


Infraestructura como código

La llamada a nuestra API se realiza después de recuperar un token de autenticación a través de Gravitee. Habíamos establecido un “límite de tarifa” de 1000 llamadas por un período de 10 minutos. Durante nuestro disparo de carga, estuvimos en varias decenas de miles de llamadas en 1 minuto. ¡Lógicamente se ha alcanzado el “límite de velocidad”!

A pesar de una modificación de la infraestructura de prueba para desactivar este “límite de velocidad”, se ha producido otro punto conflictivo.


llamar soltero

En nuestro escenario de Karate, 1 llamada a la API genera 1 llamada a Gravitee. Para varias decenas de miles de llamadas, tenemos el mismo volumen de tokens creados. Sin embargo, nuestro disparo cargado no pretende probar la robustez de Gravity. Sobre todo porque el equipo que montó esta infraestructura se había asegurado de su funcionamiento.

Y desde otro punto de vista, generar tantos tokens no tiene sentido, por lo que también podríamos crear solo uno para nuestras pruebas.

Para hacer esto, la API de Karate proporciona un método llamarSingle para llamar a un recurso una sola vez, en nuestro caso la generación del token.

var result = karate.callSingle('classpath:scenarios/api/authentification.feature', config);
Entrar en modo de pantalla completaSalir del modo de pantalla completa

El resultado de la ejecución de este comando se puede comprobar en la siguiente tabla generada, al nivel de la línea circulada en rojo: 1 única ejecución sobre el recurso POST /portador/token fue producido.

Estadísticas Gatling

Esto tiene como consecuencia tener que ejecutar nuestro tiro de carga durante la vigencia del token, so pena de generar una gran cantidad de errores. 401 – No autorizado.


Análisis de resultados

Para determinar un límite para nuestra API, realizamos varias rondas de disparos de carga. Comenzando con unos pocos cientos de llamadas por minuto, gradualmente aumentamos la cantidad de llamadas, redujimos el tiempo de ejecución, hasta degradar los tiempos de respuesta para la entrega a nuestros clientes.

En los siguientes gráficos generados por Gatling, se dispone de dos datos: el número de solicitudes y el número de usuarios en un momento t.

Estos datos son estables y muestran que no se encuentra ningún punto de estancamiento durante el disparo. El número de solicitudes es estable.

Informe de Gatling - Gráfico de recuento de solicitudes

Además de los diagramas, Gatling ofrece un informe textual con el número de solicitudes durante el disparo, el tiempo máximo de respuesta y estadísticas sobre la distribución de los tiempos de respuesta.

Rapport Gatling - información global

Un dato importante representativo de la salud de nuestra API es el consumo de CPU. Esta información está disponible en los tableros de Grafana existentes dentro de RCA, lo que nos permitirá validar nuestra interpretación de los resultados de Gatling.

Tablero Grafana

Hemos llegado a identificar un límite para nuestra API. Un plano simulando 50.000 usuarios durante 30 segundos nos da unos tiempos de respuesta aceptables, es decir, por debajo de los 800 ms.

La plataforma colaborativa creada por RCA tiene un volumen de producción de 12.000 a 16.000 usuarios por hora. Sabiendo que, además, el entorno está subdimensionado en comparación con la producción, estos 50.000 usuarios en 30 segundos podrán hacer un uso extensivo de nuestra API.


Las contribuciones de este experimento

La integración de tiros cargados en nuestro equipo fue todo un descubrimiento. Después de familiarizarnos con la API de Karate y la extensión de Gatling, pudimos explotar rápidamente nuestros primeros resultados y darnos un orden de magnitud de la capacidad de llamadas de nuestra API.

Afortunadamente estas pruebas realizadas nos permitieron detectar y corregir un problema de rendimiento. Esto es tranquilizador para futuros desarrollos y nos protegerá de otros problemas similares.

La integración de pruebas de carga en todo el equipo es algo bueno. Con el conocimiento y la automatización de los disparos de carga en GitLab CI, cualquier perfil de persona puede ejecutar disparos de carga, recuperar el gráfico y hacer una primera interpretación del mismo.

Sylvain Nael (rca) / Jean-Philippe Baconnais (Zénika)

Encuentre este artículo en el Cuenta de Sylvain en Medium y dentro de unos días en el blog de RCA.

Share:

Facebook
Twitter
Pinterest
LinkedIn

Leave a Reply

Your email address will not be published. Required fields are marked *

Social Media

Most Popular

Get The Latest Updates

Subscribe To Our Weekly Newsletter

No spam, notifications only about new products, updates.

Categories

On Key

Related Posts