Limitación de Tasa en API Management
September 16, 2022
Con el desarrollo de internet, cada vez más empresas han comenzado a adoptar tecnologías nativas de la nube y microservicios. Sin embargo, debido a las características técnicas de las arquitecturas nativas de la nube y los microservicios, debemos gestionar cientos de servicios diferentes simultáneamente. Por lo tanto, no solo debemos considerar el funcionamiento fluido de todo el sistema, sino también garantizar la seguridad y estabilidad de cada servicio basado en API.
La limitación de tasa (rate limiting) es una de las soluciones más críticas para garantizar la estabilidad de los servicios basados en API. Sin embargo, la aplicación se volvería extremadamente engorrosa si cada servicio necesitara su propia limitación de tasa. Como la entrada y salida de todo el tráfico en el mundo digital, la puerta de enlace de API (API gateway) ayuda a lograr la gestión unificada de todas las API de los servicios. Protege el funcionamiento estable del sistema. Este artículo muestra cómo logramos la limitación de tasa a través de la puerta de enlace de API Apache APISIX y describe las estrategias y técnicas de limitación de tasa.
¿Qué es la limitación de tasa?
La limitación de tasa es una estrategia para controlar el tráfico de internet y maximizar el rendimiento. Al usar la limitación de tasa, solo se permiten solicitudes que cumplan con una restricción específica para acceder al sistema; cualquier solicitud adicional que exceda la restricción se pondrá en cola, se reducirá su prioridad o incluso se rechazará o descartará. La limitación de tasa también protege al sistema de accidentes inesperados, como picos de tráfico o ataques maliciosos, y permite que el sistema brinde servicios consistentes y estables.
Por ejemplo, cuando un tuit viral genera un pico de tráfico, Twitter debe aplicar una limitación de tasa para evitar que los servidores se colapsen debido a la sobrecarga de tráfico.
¿Por qué la necesitas?
Primero, veamos algunos casos de uso simples en la vida real que utilizan la limitación de tasa. Por ejemplo, los lugares turísticos solo pueden vender un número limitado de entradas durante las vacaciones. Además, en restaurantes populares, generalmente necesitamos reservar con anticipación o esperar mucho tiempo antes de disfrutar de la comida.
En la puerta de enlace de API, la limitación de tasa también tiene muchos beneficios. La limitación de tasa impone ciertas restricciones en nuestros servicios basados en API, asegura su funcionamiento fluido y evita pérdidas innecesarias causadas por la caída de servidores debido a picos de tráfico. Aquí hemos enumerado cinco restricciones prácticas diferentes:
- Limitar la tasa de solicitudes.
- Limitar el número de solicitudes por unidad de tiempo.
- Retrasar solicitudes.
- Rechazar solicitudes de clientes.
- Limitar la tasa de respuesta.
¿Cuándo la necesitarías?
Junto con la identificación y la autenticación, la limitación de tasa puede maximizar sus ventajas y mejorar la disponibilidad del sistema de las siguientes maneras:
- Evitar ataques maliciosos.
- Asegurar el funcionamiento estable del sistema y evitar la caída de servidores debido a picos de tráfico.
- Prevenir la caída de servidores debido a picos de solicitudes causados por errores generados por servicios ascendentes o descendentes.
- Evitar llamadas API costosas demasiado frecuentes.
- Reducir el desperdicio innecesario de recursos al limitar la frecuencia de las llamadas API.
La teoría detrás de la limitación de tasa
En las secciones anteriores, hemos presentado los beneficios de la limitación de tasa. En esta sección, ¡descubramos las teorías detrás de ella! La implementación de bajo nivel de la limitación de tasa se logra mediante algoritmos específicos. Los más comúnmente utilizados incluyen:
- Algoritmo de contador
- Ventana fija
- Ventana deslizante
- Algoritmo de cubo con fugas
- Algoritmo de cubo de tokens
Algoritmo de contador
Un algoritmo de contador es relativamente fácil de entender y tiene dos tipos:
El primer tipo es el Algoritmo de ventana fija, que mantiene un contador en una unidad de tiempo fija y restablece el contador a cero si detecta que ha pasado la unidad de tiempo.
El segundo tipo es el Algoritmo de ventana deslizante, que es una mejora basada en el primero; tiene los siguientes pasos:
- Divide las unidades de tiempo en varios intervalos (cada uno llamado un bloque).
- Cada bloque tiene un contador; cualquier solicitud entrante incrementará el contador en 1.
- Después de un tiempo fijo, esta ventana de tiempo avanza un bloque.
- Calcula el total de solicitudes en esa ventana de tiempo sumando todos los contadores de los bloques en la ventana de tiempo; si el total de solicitudes excede la restricción, descartará todas las solicitudes en esa ventana de tiempo.
Algoritmo de cubo con fugas
Imagina un cubo con fugas; todas las solicitudes primero se ponen en cola y luego el cubo las envía a una tasa constante.
Si las solicitudes exceden la capacidad del cubo, el sistema descartará y rechazará cualquier solicitud que se desborde. El algoritmo de cubo con fugas puede limitar la tasa de solicitudes y asegurar que todas las solicitudes se envíen a una tasa constante, lo que crea un modo fácil de entrada pero difícil de salida.
Los pasos principales en este algoritmo:
- Todas las solicitudes se almacenan en un cubo de tamaño fijo.
- El cubo enviará solicitudes a una tasa constante hasta que el cubo esté vacío.
- Cuando el cubo está lleno, el sistema descartará cualquier solicitud adicional.
Algoritmo de cubo de tokens
El algoritmo de cubo de tokens consta de dos partes: generación de tokens y descarte. El cubo de tokens genera tokens a una tasa constante y los almacena en un cubo de almacenamiento fijo. Cuando una solicitud pasa por el cubo de tokens, la solicitud toma uno o más tokens. Cuando el número de tokens en el cubo de tokens alcanza la capacidad máxima, el cubo de tokens descartará los tokens recién generados. Además, el cubo de almacenamiento rechazará las solicitudes entrantes si no quedan tokens.
Los pasos principales del algoritmo de cubo de tokens:
- El cubo de tokens generará tokens a una tasa constante y los colocará en el cubo de almacenamiento.
- Si el cubo de tokens está lleno, los tokens recién generados se descartarán directamente. Cuando llega una solicitud, toma uno o más tokens del cubo de almacenamiento.
- Si no quedan tokens en el cubo de tokens, el sistema rechazará cualquier solicitud entrante.
Lograr la limitación de tasa a través de la puerta de enlace de API
Si solo se deben mantener unos pocos servicios basados en API, podríamos usar directamente algoritmos de limitación de tasa en el servicio. Por ejemplo, si estás usando Go para desarrollar tu sistema, usarás tollbooth
o golang.org/x/time/rate
para implementar los algoritmos. Si estás usando Lua, podrías usar los módulos de NGINX limit_req
, limit_conn
y Lua-resty-limit-traffic
para implementar los algoritmos.
Si la limitación de tasa se implementa en un servicio basado en API, las restricciones de la limitación de tasa las establecerá el servicio mismo, y cada servicio podría tener restricciones diferentes. Las restricciones y diferencias traerán problemas de gestión si el número de servicios basados en API aumenta significativamente. En ese caso, no podríamos usar la puerta de enlace de API para gestionar todos los servicios de API de manera uniforme. También podrías implementar características de negocio no relacionadas en la puerta de enlace, como identificación, autenticación, registros, observabilidad, etc., al usar la puerta de enlace de API para resolver problemas de limitación de tasa.
Apache APISIX es una puerta de enlace nativa de la nube dinámica, en tiempo real y de alto rendimiento. APISIX actualmente admite más de 80 complementos diferentes y ya ha construido un ecosistema rico. Podemos gestionar el tráfico de los servicios basados en API utilizando los complementos de APISIX, incluyendo limit-req
, limit-conn
y limit-count
. Aquí, compartiré un caso de uso para demostrar el uso de los complementos de limitación de tasa de APISIX.
Supongamos que hay un servicio basado en API (/user/login
) que ayuda a los usuarios a iniciar sesión. Para evitar ataques maliciosos y el agotamiento de recursos, necesitamos habilitar la función de limitación de tasa para garantizar la estabilidad del sistema.
Limitar solicitudes
El complemento limit-req
limita la tasa de solicitudes, utiliza el algoritmo de cubo con fugas y lo vinculamos con rutas correspondientes o clientes específicos.
Podemos usar directamente la API de administración de APISIX para crear una ruta de este tipo:
X-API-Key
es la admin_key en la configuración de APISIX.
curl http://127.0.0.1:9080/apisix/admin/routes/1 \
-H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
{
"methods": ["POST"],
"uri": "/user/login",
"plugins": {
"limit-req": {
"rate": 3,
"burst": 2,
"rejected_code": 503,
"key": "remote_addr"
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"127.0.0.1:1980": 1
}
}
}'
El significado de este fragmento de código: Usamos la dirección IP del cliente como requisito para limitar la tasa de solicitudes.
- Si la tasa de solicitudes es menor a 3 solicitudes/segundo (
rate
), entonces la solicitud es normal; - Si la tasa de solicitudes es mayor a 3 solicitudes/segundo y menor a 5 solicitudes/segundo (
rate+burst
), reduciremos la prioridad de estas solicitudes excedentes; - Si la tasa de solicitudes es mayor a 5 solicitudes/segundo (
rate+burst
), cualquier solicitud que exceda la restricción máxima devolverá el código HTTP 503.
Si deseas aprender más sobre limit-req
, consulta este documento: APISIX limit-req
Limitar conexiones
El complemento limit-conn
limita las solicitudes paralelas (o conexiones paralelas). A continuación, se muestra un fragmento de código de ejemplo para habilitar este complemento para /user/login
:
curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
{
"methods": ["POST"],
"uri": "/user/login",
"id": 1,
"plugins": {
"limit-conn": {
"conn": 3,
"burst": 2,
"default_conn_delay": 0.1,
"rejected_code": 503,
"key": "remote_addr"
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"127.0.0.1:1980": 1
}
}
}'
El significado de este fragmento de código: Usamos la dirección IP del cliente como requisito para limitar las solicitudes paralelas.
- Si las conexiones paralelas del mismo cliente son menores a 3 (
conn
), entonces responde con el estado normal 200; - Si las conexiones paralelas son mayores a 3 (
conn
) pero menores a 5 (conn+burst
), ralentizaremos las solicitudes excedentes y aumentaremos el tiempo de retraso en 0.1 segundos; - Si las conexiones paralelas son mayores a 5 (
conn+burst
), esta solicitud será rechazada y devolverá el código HTTP 503.
Si deseas aprender más sobre limit-conn
, consulta este documento: APISIX limit-conn
Limitar conteo
El complemento limit-count
es similar a la limitación de tasa de la API de Github; limita el número total de solicitudes en un intervalo de tiempo específico y devuelve el conteo restante de solicitudes en el encabezado HTTP. A continuación, se muestra un fragmento de código de ejemplo para habilitar este complemento para /user/login
:
curl -i http://127.0.0.1:9080/apisix/admin/routes/1 \
-H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
{
"uri": "/user/login",
"plugins": {
"limit-count": {
"count": 3,
"time_window": 60,
"rejected_code": 503,
"key": "remote_addr",
"policy": "local"
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"127.0.0.1:9001": 1
}
}
}'
El significado de este fragmento de código: Usamos la dirección IP del cliente como requisito para limitar el número de solicitudes; el contador se guarda localmente en la memoria.
Si hay más de 3 (count
) solicitudes dentro de 60 segundos (time_window
), las solicitudes enviadas más de 3 veces devolverán el código HTTP 503 (rejected_code
).
Si deseas aprender más sobre limit-count
, consulta este documento: APISIX limit-count
Las ventajas de la limitación de tasa de Apache APISIX
Cuando usamos NGINX para gestionar el tráfico, si el número de solicitudes API genera un pico de tráfico, NGINX expondrá sus deficiencias, y una de ellas es que no puede cargar configuraciones dinámicamente. Por otro lado, los servicios de APISIX (como Route y Service) pueden admitir la recarga en caliente de configuraciones. Incluso si hay un pico de tráfico, APISIX puede modificar instantáneamente la limitación de tasa y otras configuraciones de complementos de seguridad. Gracias al mecanismo de observación de etcd, permite que APISIX actualice la capa de datos en milisegundos sin recargar los servicios.
Además, APISIX también admite la limitación de tasa a nivel de clúster. Por ejemplo, podemos usar limit-count
para modificar la configuración de policy
a redis
o redis-cluster
. Por lo tanto, podemos limitar las tasas a nivel de clúster compartiendo resultados de cálculo entre diferentes nodos de APISIX.
Como DevOps, usar un panel gráfico para gestionar todos los servicios de API aumentaría la productividad. APISIX proporciona un panel de control visual ordenado para hacer que la modificación de configuraciones de API sea mucho más conveniente.
Conclusión
La limitación de tasa es una necesidad común en escenarios comerciales reales, y es una forma crucial de proteger el sistema de picos de tráfico y garantizar su funcionamiento fluido. La limitación de tasa es solo una parte de la gestión de servicios de API; también podemos usar muchas otras tecnologías para brindar soporte de seguridad vital y mejorar las experiencias de los usuarios.