Construyendo API Rate Limiter usando Nodejs y Redis

Codifiquemos un limitador de velocidad de API que acelerará a los usuarios en función del número de solicitudes de API que envían al servidor.

Introducción:

Imagine que está ejecutando un servicio en el que ha permitido que sus clientes llamen a las API públicas para realizar determinadas operaciones en su sistema, pero por una razón obvia no desea que bombardeen su sistema con tantas llamadas API en este momento.

Para agregar una restricción como esa, necesitamos un limitador de velocidad de API que básicamente permite solo un cierto número de solicitudes de API en un período de tiempo determinado. Por ejemplo, 1 API por segundo o 100 llamadas API por minuto, etc.

Requisitos del sistema:

Nuestro limitador de velocidad de API debería funcionar en el entorno distribuido, por lo tanto, se debe mantener la coherencia entre las solicitudes simultáneas.

El limitador de velocidad de API debe tener una opción configurable para cambiar la cantidad de solicitudes de API permitidas por el sistema.

Cómo funciona la limitación de velocidad:

La limitación de la tasa es un proceso para definir la tasa y el nivel del recurso en particular al que pueden acceder los consumidores. Usamos la aceleración para monitorear las solicitudes y permitimos las solicitudes que son válidas y están en el límite de aceleración.

Por ejemplo:

El límite de aceleración es de 3 API / seg.

Entonces, cada vez que llegan las solicitudes entrantes, verificamos el registro existente y vemos si se alcanza el límite.

Si se alcanza el acelerador, devolvemos el código de estado HTTP 429 con el mensaje “demasiadas solicitudes”.

Hay tres tipos diferentes de estrangulamiento:

  1. Limitación estricta: el número de solicitudes no puede alcanzar el límite.
  2. Limitación suave: se puede permitir que se supere el número de solicitudes en cierto porcentaje cuando se alcanza el límite de aceleración.
  3. Limitación dinámica: en la limitación dinámica, permitimos las solicitudes incluso si se alcanza el límite si los recursos están libres y disponibles.

En este artículo, vamos a codificar la aceleración estricta.

Algoritmos de limitación de velocidad:

Hay dos tipos de algoritmos de limitación de velocidad:

  • Algoritmo de ventana fija.
  • Algoritmo de ventana deslizante.

En el algoritmo de ventana fija, el marco de tiempo de la llamada a la API es fijo. Intentemos entenderlo con un ejemplo, digamos que el usuario John sAPIted consumió API a las 12:00:00 y el límite de velocidad para él es de 5 API por minuto, por lo que entre las 12:00:00 y las 12:01:00 puede realizar 5 solicitudes. API independientemente de cuándo inició el proceso de consumo de API.

En el algoritmo de ventana deslizante, el tiempo de la ventana se considera desde la hora de inicio de la llamada a la API en lugar de la hora de inicio fija.

Vamos a desarrollar el algoritmo de ventana fija para nuestro caso de uso solo para mantener la lógica simple y fácil de entender.

Diseño de sistemas de alto nivel

Rate Limiter será responsable de decidir qué solicitud serán atendidas por los servidores de API y qué solicitud será rechazada. Una vez que llega una nueva solicitud, Web Server primero le pide al Limitador de Velocidad que decida si será atendida o restringida. Si la solicitud no se limita, se pasará a los servidores API.

Algoritmo:

Estos son los pasos necesarios para realizar la limitación de velocidad.

Digamos que nuestro limitador de velocidad permite 10 solicitudes por minuto. Entonces, cada vez que ingrese una nueva solicitud, debemos hacer lo siguiente:

Si el ‘UserID’ no está presente en Redis, insértelo y configure el ‘Count’ en 1 y el ‘StartTime’ en la hora actual en formato Unix, y permita la solicitud.

De lo contrario, busque el registro de ‘UserID’ y si ‘CurrentTime – StartTime> = 1 min’, establezca ‘StartTime’ en la hora actual y ‘Count’ en 1, y permita la solicitud.

Si ‘CurrentTime – StartTime <= 1 min’ y If ‘Count <10’, incremente el Count y permita la solicitud. Si ‘Recuento> = 10’, rechace la solicitud con el código de estado 429.

¡Parece simple a la derecha! Codifiquemos.

Requisitos de Software:

Debe instalar el siguiente software en su sistema (si aún no lo ha hecho) antes de continuar, el enlace lo llevará a la página de instalación correspondiente.

  • Node.js
  • Redis
  • Postman (o su herramienta de prueba de API favorita)
  • Atom (opcional, cualquier editor funcionaría)

Crear proyecto de nodo

Cree una nueva carpeta y cambie a esa carpeta usando la línea de comando. Inicie el proyecto Node usando el siguiente comando.

npm init –y

Ahora, ejecute el siguiente comando para instalar las dependencias requeridas por el proyecto.

npm i: momento de redis expreso

Vamos a utilizar el módulo express para el servidor web. Redis para almacenar la información que limita la velocidad y el momento para manejar la información relacionada con el tiempo.

Creando el servidor

Aquí está el fragmento de código del servidor básico listo para servir API. Estamos usando el módulo express para crear el servidor.

app.js
const express = require ( ‘express’ )
const app = express ( )
const router = express. Router ( )
const rateCheck = require ( ‘./ratelimiter’ )


enrutador.
get ( ‘/’ , ( req , res ) => {

  res.
enviar (

Respuesta de la API

)
} )


aplicación.
use la
aplicación
( rateCheck )
. use la aplicación ( ‘/ api’ , enrutador )


.
escuchar ( 3000 )

En las primeras tres líneas, he declarado las dependencias y he creado la instancia de expreso y enrutador expreso.

En la cuarta línea, he incluido el archivo llamado ratelimiter.js, que en realidad es la función de middleware express. Explicaré más sobre esto en un minuto.

Hemos creado una API muy básica que devuelve la respuesta y agregamos el middleware antes del enrutador para que la función del limitador de velocidad se ejecute cada vez que se llama a una API.

Veamos la pieza de código del limitador de velocidad.

Creación de limitador de velocidad

Aquí está la pieza de código del limitador de velocidad.

ratelimiter.js
const redis = require ( ‘redis’ )
const redisClient = redis. createClient ( )
const moment = require ( ‘moment’ )


module.
exportaciones = ( req , res , siguiente ) => {

  redisClient.
existe ( req. encabezados . usuario , ( err , responder ) => {
    if ( err) {

      consola.
log ( “Redis no funciona …” )

      sistema.
exit ( 0 )
    }
    if ( responder === 1 ) {
      // el usuario existe
      // comprobar el intervalo de tiempo

      redisClient.
get ( req. encabezados . usuario , ( err , responder ) => {

        dejar datos
= JSON. analizar ( responder )

        dejar tiempo actual
= momento( ) . unix ( )

        let difference
= ( currentTime data. startTime ) / 60
        if ( diferencia > = 1 ) {

          let body
= {
            ‘count’ : 1 ,
            ‘startTime’ : moment ( ) . unix ( )
          }

          redisClient.
set ( req. encabezados . usuario , JSON. stringify( cuerpo ) )
          // permitir la solicitud

          next
( )
        }
        if ( diferencia < 1 ) {
          if ( recuento de datos > 3 ) {
            return res. json ( { “error” : 1 , “message” : “límite acelerado excedido …” } )
          }
          // actualiza el recuento y permite los

          datos de
la solicitud .
count ++

          redisClient.
conjunto ( req.encabezados . usuario , JSON. stringify ( data ) )
          // permitir solicitud

          next
( )
        }
      } )
    } else {
      // agregar nuevo usuario

      let body
= {
        ‘count’ : 1 ,
        ‘startTime’ : moment ( ) . unix ( )
      }

      redisClient.
set ( req. encabezados . usuario , JSON. stringify ( cuerpo) )
      // permitir la solicitud

      siguiente
( )
    }
  } )
}

Ok, déjame explicarte.

Todo el código se divide en dos partes importantes.

  1. Si es la primera solicitud, agregue Redis y permita la solicitud.
  2. Si se trata de una solicitud recurrente, verifique el recuento de solicitudes y la diferencia de tiempo y permita / rechace la solicitud.

En el primer bloque de código, estoy verificando si este usuario existe o no, si existe, obtengo información completa sobre el usuario de Redis y hago esto:

¿La marca de tiempo de la solicitud actual y la marca de tiempo de la última solicitud registrada en Redis es más de 1 minuto? Si es así, permita la solicitud y restablezca la hora en Redis.

Si no es así, verifique si el usuario ha solicitado menos o igual a tres solicitudes. Si es menos de tres, permita la solicitud.

Si son más de tres solicitudes, rechace la solicitud y devuelva la respuesta.

Ok, basta de hablar. Ejecutemos el código.

Ejecutando el código

Cambie a la carpeta donde ha colocado el código usando el terminal y ejecute este comando.

nodo app.js

Y acceda a esta API utilizando POSTMAN o cualquier otro simulador de API.

http: // localhost: 3000 / api

Nota: asegúrese de que en los encabezados le pasa la clave de usuario y algún valor aleatorio.

O

Mire el video a continuación para ver cómo funciona.

Resumen

Espero que les guste este artículo profesional de Codeforgeek. Esta es la primera entrada y voy a enviar mucho más contenido como este, también estoy pensando en hacer videos y audio sobre varios temas.

Hágame saber lo que piensa sobre este artículo y cómo puede ayudarlo a decodificar el software existente y cómo funcionan.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *