Agrupación de solicitudes de API por lotes con NGINX Plus y el módulo JavaScript de NGINX

NGINX | 24 de mayo de 2018

La versión del módulo JavaScript de NGINX publicada con NGINX Plus R15 ahora puede emitir subsolicitudes, lo que significa que se pueden iniciar solicitudes mediante código JavaScript. Esto permite abordar todo un nuevo conjunto de casos de uso.

Uno de estos casos de uso consiste en agrupar solicitudes de API, de modo que una única solicitud de API de un cliente pueda convertirse en varias solicitudes de API dirigidas a un conjunto de servidores backend, y las respuestas se combinen en una única respuesta para el cliente. En este blog utilizamos como ejemplo un sitio de comercio electrónico: cuando el cliente solicita información sobre un producto concreto, se realizan subsolicitudes a tres servicios backend: catálogo, inventario y reseñas de clientes.

Este artículo se basa en el ejemplo de subsolicitudes del anuncio de NGINX Plus R15, que muestra cómo utilizar subsolicitudes para enviar la misma solicitud a dos servidores backend y devolver al cliente únicamente la primera respuesta.

[Editor : Esta entrada forma parte de una serie en la que se analizan casos de uso del módulo JavaScript de NGINX. Para consultar la lista completa, véase Casos de uso del módulo JavaScript de NGINX.

La entrada se ha actualizado para usar la directiva js_import, que sustituye a la directiva js_include en NGINX Plus R23 y versiones posteriores. Para obtener más información, consulte la documentación de referencia del módulo JavaScript de NGINX ; en la sección Configuración de ejemplo se muestra la sintaxis correcta para los archivos de configuración de NGINX y JavaScript.]

Introducción

El objetivo de esta publicación es proporcionar ejemplos funcionales, sencillos y claros de agrupación de solicitudes de API. Los ejemplos cumplen todos los requisitos siguientes:

  • El método HTTP «GET» se utiliza para todas las solicitudes.
  • Todas las respuestas están en formato JSON.
  • Se admiten dos tipos de solicitudes de API. Tenga en cuenta que, con cualquiera de ellos, puede haber argumentos adicionales en la cadena de consulta.
    • El argumento del programa de la API es el elemento final del URI. A esto lo denominamos estilo de solicitud de elemento final. En nuestro ejemplo, una solicitud de cliente a /batch-api/product/14286 genera solicitudes a /myapi/catalog/14286, /myapi/inventory/14286 y /myapi/review/14286.
    • El argumento se identifica en la cadena de consulta del URI. A esto lo denominamos «estilo de solicitud mediante cadena de consulta». En el ejemplo, una solicitud a /batch-api2/product?item=14286 genera solicitudes a /myapi/catalog.php?item=14286, /myapi/inventory.php?item=14286 y /myapi/review.php?item=14286.
  • El conjunto de subsolicitudes activadas por una solicitud del cliente se puede configurar dinámicamente, lo que significa que podemos modificarlo sin editar manualmente la configuración de NGINX Plus ni volver a cargarla.
  • Las solicitudes de la API a los servidores backend son independientes entre sí.

Descripción general de la solución

Además de utilizar la nueva función de subsolicitudes de NGINX JavaScript, esta solución emplea la función de almacén de pares clave-valor de NGINX Plus, lo que permite realizar cambios de configuración de forma dinámica mediante la API de NGINX Plus.

Los siguientes gráficos ilustran los dos estilos de solicitud compatibles.

Estilo de solicitud de elemento final:

El cliente realiza solicitudes a una API siguiendo el estilo de elemento final

Estilo de solicitud mediante cadena de consulta:

El cliente realiza solicitudes a una API mediante cadenas de consulta

En ambos ejemplos, el cliente necesita obtener información sobre un producto de los servicios de catálogo, inventario y reseñas. Envía una solicitud a NGINX Plus, ya sea incluyendo el número de artículo como parte del URI o en la cadena de consulta. A continuación, se envían solicitudes a los tres servicios y las respuestas se agrupan en una única respuesta para el cliente.

Para que esto funcione con NGINX Plus, se necesitan dos componentes: un programa JavaScript y la configuración de NGINX Plus.

El programa JavaScript

La función de JavaScript batchAPI() se invoca para cada solicitud del cliente. Obtiene del almacén de clave-valor la lista de URI de API separadas por comas y las recorre, realizando una subsolicitud para cada una y especificando la función de devolución de llamada done() para procesar cada respuesta. En las solicitudes de tipo elemento final, el último elemento del URI, almacenado en la variable de NGINX $uri_suffix, se pasa como cadena de consulta de cada subsolicitud, junto con cualquier otro argumento de la cadena de consulta del URI original del cliente. En las solicitudes de tipo cadena de consulta, la cadena de consulta de las solicitudes del cliente se pasa como cadena de consulta de cada subsolicitud.

Las llamadas se realizan en el orden en que aparecen en el almacén de clave-valor, pero son asíncronas, por lo que las respuestas pueden llegar en cualquier orden. Las respuestas se agrupan en una única respuesta al cliente en el orden en que se reciben. A continuación se muestra una versión mínima del programa JavaScript:

Cargando ejemplo de código…

En el repositorio de GitHub Gist hay disponible una versión del programa JavaScript con una gestión de errores, un registro y comentarios más exhaustivos, denominada «batch-api.js».

Configuración mínima de NGINX Plus

La siguiente configuración de NGINX Plus implementa los dos estilos de solicitud descritos anteriormente mediante un grupo de servidores ascendentes. Para simplificar, esta configuración presupone que los servidores ascendentes pueden convertir una llamada con el formato /myapi/servicio/n.º de elemento (estilo de elemento final) en /myapi/servicio.php/?item=n.º de elemento (estilo de cadena de consulta), que es el formato de URI «nativo» de PHP, el lenguaje utilizado para nuestros servicios de ejemplo de catálogo, inventario y reseñas.

Para obtener una configuración de NGINX Plus más completa que realice la conversión, consulte Ampliación de la configuración de NGINX para convertir URI más adelante.

Veamos el archivo de configuración sección por sección y expliquemos qué hace cada parte:

  • Importa el archivo JavaScript:

    Cargando ejemplo de código…

  • Defina un almacén de clave-valor para guardar la lista de solicitudes de API en las que el último elemento del URI identifica el argumento del programa de la API. La clave utiliza la variable $uri_prefix para capturar la parte del URI anterior a la última /:

    Cargando ejemplo de código…

    En NGINX Plus R16 y versiones posteriores, puede aprovechar dos funciones adicionales de clave-valor: Para obtener instrucciones sobre cómo configurar la sincronización de almacenes de clave-valor, consulte la Guía de administración de NGINX Plus.
    • Establezca un tiempo de expiración para las entradas de un almacén de clave-valor añadiendo el parámetro timeout a la directiva keyval_zone. Por ejemplo, para que cada URI agrupado expire diariamente, añada timeout=1d.
    • Sincronice el almacén de clave-valor en un clúster de instancias de NGINX Plus añadiendo el parámetro sync a la directiva keyval_zone. En este caso, también debe incluir el parámetro timeout.
  • Defina otro almacén de clave-valor para las API en las que el argumento se identifica en la cadena de consulta. En este caso, la clave ($uri) captura el URI completo, sin incluir la cadena de consulta:

    Cargando ejemplo de código…

  • Defina dos mapas para dividir el URI en dos partes en el caso de las API que aceptan solicitudes en las que el argumento es el último elemento del URI. La variable $uri_prefix captura los elementos del URI anteriores a la última / y $uri_suffix captura el elemento final:

    Cargando ejemplo de código…

  • Defina el grupo de servidores upstream de los servidores de API (en este caso, se ejecutan en localhost junto con NGINX Plus):

    Cargando ejemplo de código…

  • Defina el servidor virtual que gestiona las solicitudes y subsolicitudes de los clientes:

    Cargando ejemplo de código…

  • Defina una ubicación para gestionar las solicitudes de clientes que utilizan el estilo de elemento final, lo cual se indica a la función batchAPI estableciendo la variable $batch_api_arg_in_uri en on:

    Cargando ejemplo de código…

  • Defina una ubicación para gestionar las solicitudes de clientes que utilizan el formato de cadena de consulta, lo cual se indica a la función batchAPI estableciendo la variable $batch_api_arg_in_uri en off:

    Cargando ejemplo de código…

  • Defina la ubicación que gestiona las subsolicitudes:

    Cargando ejemplo de código…

  • Habilite la API de NGINX Plus para poder mantener los datos en el almacén de clave-valor:

    Cargando ejemplo de código…

Esta es la configuración completa:

Cargando ejemplo de código…

Configuración de las solicitudes de API por lotes

Utilizamos la función de almacén de pares clave-valor de NGINX Plus para asociar las solicitudes entrantes de los clientes a un conjunto de solicitudes de API que se deben ejecutar. La configuración de la sección anterior define almacenes de pares clave-valor independientes para los dos tipos de solicitud:

  • El almacén de clave-valor para el estilo de elemento final se denomina batch_api y la clave es la variable $uri_prefix, que captura los elementos anteriores a la última / del URI de la solicitud.
  • El almacén de clave-valor para el formato de cadena de consulta se denomina batch_api2 y la clave es la variable $uri, que captura el URI completo de la solicitud sin la cadena de consulta.

En ambos almacenes de clave-valor, el valor asociado a cada clave es una lista de URI separadas por comas que están disponibles en tiempo de ejecución en las variables «$batch_api» o «$batch_api2».

Para las solicitudes de tipo elemento final, queremos asignar una solicitud de cliente a /batch-api/product a solicitudes dirigidas a los tres servicios /myapi/catalog, /myapi/inventory y /myapi/review, de modo que una solicitud a /batch-api/product/14286 dé lugar a solicitudes a /myapi/catalog/14286, /myapi/product/14286 y /myapi/review/14286.

Para añadir estas asignaciones al almacén de clave-valor batch_api, enviamos la siguiente solicitud a la instancia de NGINX Plus que se ejecuta en la máquina local:

$ curl -iX POST -d '{"/batch-api/product":"/myapi/catalog,/myapi/inventory,/myapi/review"}' http://localhost/api/3/http/keyvals/batch_api

Para las solicitudes con parámetros de consulta, queremos asignar una solicitud del cliente a /batch-api2/product a solicitudes dirigidas a los tres servicios /myapi/catalog.php, /myapi/inventory.php y /myapi/review.php, de modo que una solicitud a /batch-api2/product?item=14286 genere solicitudes a /myapi/catalog?item=14286, /myapi/product?item=14286 y /myapi/review?item=14286.

Para añadir estas asignaciones al almacén de clave-valor batch_api2, enviamos esta solicitud:

$ curl -iX POST -d '{"/batch-api2/product":"/myapi/catalog.php,/myapi/inventory.php,/myapi/review.php"}' http://localhost/api/3/http/keyvals/batch_api2

Ejecución de los ejemplos

Las mismas páginas PHP gestionan las solicitudes realizadas con ambos estilos. Para simplificar, suponemos que los servidores backend pueden convertir los URI con formato de elemento final (/myapi/service/item#) en URI con formato de cadena de consulta (/myapi/service.php?item=item#). No es necesario convertir los URI con formato de cadena de consulta, ya que ese es el formato de URI «nativo» de los programas PHP.

Todos los servicios devuelven una respuesta en formato JSON que incluye el nombre del servicio y el argumento del elemento. Por ejemplo, una solicitud a /myapi/catalog.php?item=14286 da como resultado la siguiente respuesta de catalog.php:

{"service":"Catalog","item":"14286"}

Aunque los programas PHP utilizados en estos ejemplos incluyen el nombre del servicio en la respuesta, puede que no sea así para todos los servicios. Para facilitar la asociación de las respuestas con los servicios que las generaron, el programa JavaScript incluye el URI en la respuesta agregada.

Por ejemplo, la respuesta agregada a una solicitud de /batch-api/product/14286 es la siguiente (aunque el orden de las tres respuestas que la componen puede variar):

[["/myapi/review/14286",{"service":"Review","item":"14286"}],["/myapi/inventory/14286",{"service":"Inventory","item":"14286"}],["/myapi/catalog/14286",{"service":"Catalog","item":"14286"}]]

Ampliación de la configuración de NGINX Plus para traducir URI

Como se ha mencionado, la configuración mínima de NGINX Plus descrita anteriormente presupone que los servidores de API pueden convertir los URI con el formato /myapi/servicio/n.º de elemento en /myapi/servicio.php/?item=n.º de elemento. También podemos implementar esta conversión en la configuración de NGINX Plus realizando los siguientes cambios.

  • Añada un nuevo grupo upstream para recibir las subsolicitudes:

    Cargando ejemplo de código…

  • Añada un nuevo servidor virtual para escuchar las solicitudes recibidas por el grupo ascendente services. Cuando se reciben solicitudes con formato de cadena de consulta, simplemente se redirigen mediante proxy al grupo ascendente api_servers porque el URI ya tiene la extensión .php. Cuando se reciben solicitudes con formato de elemento final, el URI se reescribe para eliminar el último elemento del URI y convertirlo en un argumento de cadena de consulta:

    Cargando ejemplo de código…

  • Cambie la ubicación /myapi location para que redirija las solicitudes al nuevo grupo de servidores upstream:

    Cargando ejemplo de código…

Esta es la configuración completa:

Cargando ejemplo de código…

Componentes adicionales

Los programas JavaScript de ejemplo y las configuraciones de NGINX Plus pueden adaptarse a otros estilos de API, pero, si desea realizar pruebas con todos los componentes utilizados para crear esta entrada del blog, puede encontrarlos en nuestro repositorio de Gist en GitHub, incluida la configuración de NGINX Unit para servir las páginas PHP:

batch-api.js
catalog.php
inventory.php
review.php
unit.config

Conclusión

Estos ejemplos muestran cómo agrupar solicitudes de API y proporcionar una respuesta agregada al cliente. El almacén de clave-valor de NGINX Plus permite configurar dinámicamente las solicitudes de API mediante la API de NGINX Plus. El funcionamiento concreto de los sistemas de API varía considerablemente, por lo que se pueden realizar numerosas mejoras en este ejemplo para adaptarlo a las necesidades de una API específica.

Puede empezar a probar las subsolicitudes de JavaScript de NGINX con NGINX Open Source, pero si quiere probar los ejemplos de agrupación de solicitudes de API u otros casos de uso que aprovechen las funciones de NGINX Plus, como el almacén de clave-valor y la API de NGINX Plus, solicite una prueba gratuita de 30 días y empiece a experimentar.


Compartir

Sobre el autor

Rick Nelson
Rick NelsonVicepresidente regional de Ingeniería de Soluciones

Más artículos de Rick Nelson

Artículos relacionados del blog

Únete a F5 NGINX en AppWorld 2024
NGINX | 04/01/2024

Únete a F5 NGINX en AppWorld 2024

Descubre las numerosas razones para asistir al evento insignia de F5, que incluirá un emocionante anuncio sobre la cartera de productos NGINX.

Rotación de certificados SSL/TLS sin reinicios en NGINX Open Source
NGINX | 26/09/2023

Rotación de certificados SSL/TLS sin reinicios en NGINX Open Source

La función de diccionario compartido permite configurar NGINX sin necesidad de reiniciarlo al renovar los certificados SSL/TLS.

Exposición de APIs en Kubernetes
NGINX | 10/03/2022

Exposición de APIs en Kubernetes

La unidad 2 de Microservices March 2022 se centra en cómo exponer tus API en Kubernetes. Aquí tienes enlaces a los recursos que necesitas: la retransmisión en directo del 14 de marzo, artículos de blog y otros recursos de preparación, y el laboratorio práctico «Protege las API de Kubernetes mediante la limitación de solicitudes».

NGINX Sprint 2.0: visión clara, código renovado y nuevos compromisos con el código abierto
NGINX | 23/08/2021

NGINX Sprint 2.0: visión clara, código renovado y nuevos compromisos con el código abierto

Hoy, en NGINX Sprint 2.0, anunciamos cómo respaldaremos nuestra visión del futuro de las aplicaciones modernas con una mayor presencia en la comunidad de código abierto, incluida la participación en el proyecto comunitario Kubernetes, nuevos proyectos de software de código abierto y la arquitectura de referencia para aplicaciones modernas.

Presentamos NGINX Plus R22
NGINX | 09/06/2020

Presentamos NGINX Plus R22

NGINX Plus R22 incorpora nuevas funcionalidades, como la compatibilidad con OCSP para verificar la revocación de certificados en TLS mutuo, el uso de varios proveedores de identidad OIDC en una configuración, el seguimiento en tiempo real de la limitación de solicitudes y conexiones en el panel de NGINX Plus y mejoras en NGINX JavaScript.

Presentamos NGINX Plus R17
NGINX | 11/12/2018

Presentamos NGINX Plus R17

NGINX Plus R17 incorpora compatibilidad con la limitación de velocidad en dos fases y con TLS 1.3, la versión más reciente del protocolo Transport Layer Security. La configuración de OpenID Connect es más sencilla y NGINX ModSecurity WAF es el doble de rápido que antes. También se ha actualizado el módulo JavaScript de NGINX.