Estrategias prácticas para la limitación de tasa en APIs GraphQL

January 4, 2024

Technology

Implementar la limitación de tasa en las API REST es relativamente sencillo, ya que comúnmente utilizamos rutas URI para representar recursos específicos de la API y métodos HTTP para indicar operaciones sobre los recursos. La capa de proxy puede aplicar fácilmente reglas predefinidas de limitación de tasa basándose en esta información.

Sin embargo, el escenario se vuelve significativamente más complejo cuando se trata de API GraphQL. Profundicemos en cómo superar estos desafíos.

Escenarios Simples

A diferencia de las API REST, GraphQL utiliza un lenguaje de consulta propio. Ya no depende de rutas y métodos HTTP para la recuperación y manipulación de recursos, sino que unifica la consulta de datos y las operaciones bajo Query y Mutation, donde Query obtiene datos y Mutation realiza manipulaciones de datos como crear, actualizar y eliminar.

GET /users
GET /users/1
POST /users
PUT /users/1
DELETE /users/1

query { users { fullName } }
query { user(id: 1) { fullName } }
mutation { createUser(user: { lastName: "Jack" }) { id, fullName } }
mutation { updateUser (id: 1, update: { lastName: "Marry" }) { fullName } }
mutation { deleteUser (id: 1) }

Los ejemplos anteriores resaltan el cambio en los métodos de consulta de la API. A diferencia de REST, GraphQL se asemeja a llamar funciones sobre recursos, pasando los parámetros de entrada necesarios, con la respuesta conteniendo los datos consultados. Además de las diferencias en los métodos de consulta, GraphQL expone las API típicamente a través de un único endpoint (por ejemplo, /graphql), con las consultas y los parámetros de entrada enviados a través del cuerpo POST.

Considere el siguiente ejemplo:

query {
    users {
        fullName
    }
    photos {
        url
        uploadAt
    }
}

En este escenario, simulando la página de inicio de un álbum, una llamada API al endpoint /graphql consulta tanto las listas de usuarios como de fotos simultáneamente. Ahora, considere si las estrategias tradicionales de proxy inverso, ejecutadas a nivel de solicitud, siguen siendo aplicables a las API GraphQL.

La respuesta es no. Los servidores de proxy inverso tradicionales no pueden manejar efectivamente las llamadas API GraphQL que contienen las consultas en sí, haciendo imposible aplicar políticas como la limitación de tasa. Para las API GraphQL, la granularidad de las "solicitudes HTTP" parece demasiado gruesa.

Sin embargo, la puerta de enlace API, Apache APISIX incorpora soporte integrado para capacidades de GraphQL a HTTP. Los administradores pueden preconfigurar una declaración de consulta, permitiendo que los clientes la llamen directamente a través de un POST HTTP sin entender los detalles de GraphQL, solo proporcionando los parámetros de entrada necesarios. Esto no solo mejora la seguridad, sino que también permite la aplicación de políticas de API HTTP en este contexto.

limitación de tasa

Efectivamente, esto transforma las consultas dinámicas de GraphQL en consultas estáticas basadas en conocimiento proporcionadas por los proveedores de API, presentando tanto ventajas como desventajas. A veces, podríamos no querer sacrificar la característica de consulta dinámica de GraphQL. Continuemos la discusión de otros escenarios.

Escenarios Complejos

GraphQL utiliza su lenguaje especializado para el modelado de datos y la descripción de API, permitiendo estructuras de datos anidadas. Ampliando el ejemplo anterior:

query {
    photos(first: 10) {
        url
        uploadAt
        publisher {
            fullName
            avatar
        }
        comments(first: 10) {
            content
            sender {
                fullName
                avatar
            }
        }
    }
    // users...
}

En este caso, simulando la recuperación de las primeras 10 fotos, incluyendo el editor de cada foto y los primeros 10 comentarios con sus remitentes, el servicio backend debe manejar consultas que involucran múltiples tablas de base de datos o llamadas a microservicios. En tales escenarios de consultas anidadas, a medida que la cantidad de datos y los niveles de anidación aumentan, el estrés computacional en los servicios backend y las bases de datos aumenta exponencialmente.

Para evitar que consultas complejas abrumen el servicio, podríamos querer inspeccionar y bloquear tales consultas en la capa de proxy. Para aplicar esta estrategia, el componente proxy debe analizar las declaraciones de consulta en datos estructurados, recorrerlos para obtener los campos anidados en cada capa, y seguir la práctica común de GraphQL de asignar valores de complejidad a los campos como costos de consulta. Luego, se pueden aplicar límites globales sobre el costo total de la consulta. Para la consulta anterior, asumiendo un costo de 1 para cada campo individual:

10 * photo (url + uploadAt + publisher.fullName + publisher.avatar + 10 * comment (content + sender.fullName + sender.avatar))

10 * (1 + 1 + 1 + 1 + 10 * (1 + 1 + 1)) = 340

Con un costo total de consulta de 340, parece aceptable, y podemos configurar límites de costo de consulta de API basados en tales reglas. Sin embargo, si un cliente malicioso intenta obtener datos de 100 fotos en una sola consulta, el costo de la consulta se disparará a 3400, superando el límite predefinido y resultando en una solicitud denegada.

Más allá de restringir el costo máximo por consulta de cliente, se pueden aplicar límites adicionales en intervalos de tiempo, como permitir a los clientes un total de 2000 consultas por minuto y rechazar consultas excesivas, lo que puede frustrar a los rastreadores maliciosos.

Para implementar tales capacidades, el componente proxy debe analizar y calcular los costos de consulta. API7 Enterprise soporta estas características, permitiendo el análisis dinámico de consultas GraphQL y la implementación de límites de tasa basados en configuraciones.

Las API GraphQL enfrentan desafíos en la capa de proxy, donde los proxies inversos tradicionales luchan por percibir y manejar efectivamente la complejidad y las relaciones de anidación dentro de las declaraciones de consulta GraphQL. En contraste, las tecnologías de puerta de enlace API resultan invaluables para superar estos desafíos donde API7 Enterprise puede ser una excelente opción.

Tags: