Editor – Esta serie de siete artículos ya está completa:
También puede descargar el conjunto completo de artículos, además de información sobre la implementación de microservicios utilizando NGINX Plus, como un libro electrónico: Microservicios: Desde el diseño hasta la implementación . Además, consulte la nueva página de Soluciones de Microservicios .
El primer artículo de esta serie de siete partes sobre el diseño, la creación y la implementación de microservicios presentó el patrón de arquitectura de microservicios. Se discutieron los beneficios y desventajas de usar microservicios y cómo, a pesar de la complejidad de los microservicios, suelen ser la opción ideal para aplicações complejas. Este es el segundo artículo de la serie y abordará la creación de microservicios utilizando una API Gateway.
Cuando decide construir su aplicação como un conjunto de microservicios, debe decidir cómo interactuarán los clientes de su aplicación con los microservicios. Con una aplicação monolítica solo hay un conjunto de puntos finales (normalmente replicados y con equilibrio de carga). Sin embargo, en una arquitectura de microservicios, cada microservicio expone un conjunto de puntos finales que suelen ser de granularidad fina. En este artículo, examinamos cómo esto afecta la comunicación entre el cliente y la aplicação y proponemos un enfoque que utiliza una API Gateway .
Imaginemos que estás desarrollando un cliente móvil nativo para una aplicação de compras. Es probable que necesites implementar una página de detalles del producto, que muestre información sobre cualquier producto determinado.
Por ejemplo, el siguiente diagrama muestra lo que verá al desplazarse por los detalles del producto en la aplicação móvil Android de Amazon.
Aunque se trata de una aplicação para teléfonos inteligentes, la página de detalles del producto muestra mucha información. Por ejemplo, no solo hay información básica del producto (como nombre, descripción y precio), sino que esta página también muestra:
Al utilizar una arquitectura de aplicação monolítica, un cliente móvil recuperaría estos datos realizando una única llamada REST ( GET
api.company.com/productdetails/productId
) a la aplicação. Un equilibrador de carga dirige la solicitud a una de N instancias de aplicação idénticas. Luego, la aplicação consultaría varias tablas de la base de datos y devolvería la respuesta al cliente.
Por el contrario, cuando se utiliza la arquitectura de microservicios, los datos que se muestran en la página de detalles del producto son propiedad de múltiples microservicios. A continuación se muestran algunos de los posibles microservicios que poseen datos que se muestran en la página de detalles del producto de ejemplo:
Necesitamos decidir cómo el cliente móvil accede a estos servicios. Veamos las opciones.
En teoría, un cliente podría realizar solicitudes a cada uno de los microservicios directamente. Cada microservicio tendría un punto final público ( https://serviceName.api.company.name ). Esta URL se asignaría al balanceador de carga del microservicio, que distribuye las solicitudes entre las instancias disponibles. Para recuperar los detalles del producto, el cliente móvil realizaría solicitudes a cada uno de los servicios enumerados anteriormente.
Desafortunadamente, esta opción presenta desafíos y limitaciones. Un problema es la falta de correspondencia entre las necesidades del cliente y las API detalladas expuestas por cada uno de los microservicios. El cliente en este ejemplo tiene que realizar siete solicitudes independientes. En aplicações más complejas podría ser necesario fabricar muchas más. Por ejemplo, Amazon describe cómo cientos de servicios participan en la representación de su página de producto. Si bien un cliente podría realizar esa cantidad de solicitudes a través de una LAN, probablemente sería demasiado ineficiente en Internet público y definitivamente sería poco práctico en una red móvil. Este enfoque también hace que el código del cliente sea mucho más complejo.
Otro problema con el cliente que llama directamente a los microservicios es que algunos podrían usar protocolos que no son compatibles con la web. Un servicio podría utilizar el RPC binario Thrift mientras que otro servicio podría utilizar el protocolo de mensajería AMQP. Ninguno de estos protocolos es especialmente compatible con navegadores o firewalls y es mejor utilizarlos internamente. Una aplicação debe utilizar protocolos como HTTP y WebSocket fuera del firewall.
Otro inconveniente de este enfoque es que dificulta la refactorización de los microservicios. Con el tiempo, es posible que queramos cambiar la forma en que se divide el sistema en servicios. Por ejemplo, podríamos fusionar dos servicios o dividir un servicio en dos o más servicios. Sin embargo, si los clientes se comunican directamente con los servicios, entonces realizar este tipo de refactorización puede ser extremadamente difícil.
Debido a este tipo de problemas, rara vez tiene sentido que los clientes hablen directamente con los microservicios.
Generalmente, un enfoque mucho mejor es utilizar lo que se conoce como API Gateway . Un API Gateway es un servidor que es el único punto de entrada al sistema. Es similar al patrón Fachada del diseño orientado a objetos. API Gateway encapsula la arquitectura interna del sistema y proporciona una API adaptada a cada cliente. Podría tener otras responsabilidades como autenticación, supervisión, equilibrio de carga, almacenamiento en caché, gestión y modelado de solicitudes, y manejo de respuestas estáticas.
El siguiente diagrama muestra cómo una API Gateway normalmente encaja en la arquitectura:
API Gateway es responsable del enrutamiento de solicitudes, la composición y la traducción del protocolo. Todas las solicitudes de los clientes pasan primero por la API Gateway. Luego, dirige las solicitudes al microservicio apropiado. La API Gateway a menudo manejará una solicitud invocando múltiples microservicios y agregando los resultados. Puede traducir entre protocolos web como HTTP y WebSocket y protocolos no compatibles con la web que se utilizan internamente.
API Gateway también puede proporcionar a cada cliente una API personalizada. Normalmente, expone una API general para clientes móviles. Consideremos, por ejemplo, el escenario de los detalles del producto. API Gateway puede proporcionar un punto final ( /productdetails?productid= xxx ) que permite a un cliente móvil recuperar todos los detalles del producto con una sola solicitud. API Gateway maneja la solicitud invocando los distintos servicios (información del producto, recomendaciones, reseñas, etc.) y combinando los resultados.
Un gran ejemplo de una API Gateway es la API Gateway de Netflix . El servicio de transmisión Netflix está disponible en cientos de tipos diferentes de dispositivos, incluidos televisores, decodificadores, teléfonos inteligentes, sistemas de juegos, tabletas, etc. Inicialmente, Netflix intentó proporcionar una API única para su servicio de transmisión. Sin embargo, descubrieron que no funcionaba bien debido a la amplia gama de dispositivos y sus necesidades únicas. En la actualidad, utilizan una API Gateway que proporciona una API adaptada a cada dispositivo ejecutando un código adaptador específico del dispositivo. Un adaptador normalmente maneja cada solicitud invocando en promedio entre seis y siete servicios de backend. La API Gateway de Netflix maneja miles de millones de solicitudes por día.
Como era de esperar, el uso de una API Gateway tiene ventajas y desventajas. Una de las principales ventajas de utilizar una API Gateway es que encapsula la estructura interna de la aplicação. En lugar de tener que invocar servicios específicos, los clientes simplemente hablan con la puerta de enlace. API Gateway proporciona una API específica para cada tipo de cliente. Esto reduce el número de conexiones entre el cliente y la aplicação. También simplifica el código del cliente.
La API Gateway también tiene algunos inconvenientes. Es otro componente de alta disponibilidad que debe desarrollarse, implementarse y administrarse. También existe el riesgo de que API Gateway se convierta en un cuello de botella durante el desarrollo. Los desarrolladores deben actualizar API Gateway para exponer los puntos finales de cada microservicio. Es importante que el proceso de actualización de API Gateway sea lo más ligero posible. De lo contrario, los desarrolladores se verán obligados a esperar en la cola para actualizar la puerta de enlace. Sin embargo, a pesar de estos inconvenientes, para la mayoría de las aplicações del mundo real tiene sentido utilizar una API Gateway.
Ahora que hemos visto las motivaciones y las desventajas de usar una API Gateway, veamos varias cuestiones de diseño que debes tener en cuenta.
Sólo un puñado de empresas operan a la escala de Netflix y necesitan gestionar miles de millones de solicitudes al día. Sin embargo, para la mayoría de las aplicações , el rendimiento y la escalabilidad de API Gateway suelen ser muy importantes. Por lo tanto, tiene sentido construir la API Gateway en una plataforma que admita E/S asincrónica y sin bloqueos. Existe una variedad de tecnologías diferentes que pueden utilizarse para implementar un API Gateway escalable. En la JVM puedes utilizar uno de los marcos basados en NIO como Netty, Vertx, Spring Reactor o JBoss Undertow. Una opción popular que no es JVM es Node.js, que es una plataforma construida sobre el motor JavaScript de Chrome. Otra opción es utilizar NGINX Plus . NGINX Plus ofrece un servidor web y un proxy inverso maduros, escalables y de alto rendimiento que se implementan, configuran y programan fácilmente. NGINX Plus puede administrar autenticación, control de acceso, solicitudes de equilibrio de carga, respuestas de almacenamiento en caché y brinda controles y monitoreo del estado de las aplicação.
API Gateway maneja algunas solicitudes simplemente enviándolas al servicio backend apropiado. Maneja otras solicitudes invocando múltiples servicios backend y agregando los resultados. Con algunas solicitudes, como una solicitud de detalles de un producto, las solicitudes a los servicios backend son independientes entre sí. Para minimizar el tiempo de respuesta, API Gateway debe realizar solicitudes independientes simultáneamente. A veces, sin embargo, existen dependencias entre solicitudes. Es posible que API Gateway primero deba validar la solicitud llamando a un servicio de autenticación, antes de enrutar la solicitud a un servicio backend. De manera similar, para obtener información sobre los productos en la lista de deseos de un cliente, API Gateway primero debe recuperar el perfil del cliente que contiene esa información y luego recuperar la información de cada producto. Otro ejemplo interesante de composición de API es Netflix Video Grid .
Escribir código de composición de API utilizando el enfoque de devolución de llamada asincrónica tradicional lo lleva rápidamente al infierno de las devoluciones de llamadas. El código será enredado, difícil de entender y propenso a errores. Un enfoque mucho mejor es escribir el código de API Gateway en un estilo declarativo utilizando un enfoque reactivo. Algunos ejemplos de abstracciones reactivas incluyen Future en Scala, CompletableFuture en Java 8 y Promise en JavaScript. También existen las Extensiones Reactivas (también llamadas Rx o ReactiveX), que fueron desarrolladas originalmente por Microsoft para la plataforma .NET. Netflix creó RxJava para la JVM específicamente para utilizar en su API Gateway. También existe RxJS para JavaScript, que se ejecuta tanto en el navegador como en Node.js. El uso de un enfoque reactivo le permitirá escribir un código API Gateway simple pero eficiente.
Una aplicação basada en microservicios es un sistema distribuido y debe utilizar un mecanismo de comunicación entre procesos. Hay dos estilos de comunicación entre procesos. Una opción es utilizar un mecanismo asincrónico basado en mensajería. Algunas implementaciones utilizan un agente de mensajes como JMS o AMQP. Otros, como Zeromq, no tienen intermediarios y los servicios se comunican directamente. El otro estilo de comunicación entre procesos es un mecanismo sincrónico como HTTP o Thrift. Un sistema normalmente utilizará estilos tanto asincrónicos como sincrónicos. Incluso podría utilizar múltiples implementaciones de cada estilo. En consecuencia, la API Gateway deberá soportar una variedad de mecanismos de comunicación.
API Gateway necesita conocer la ubicación (dirección IP y puerto) de cada microservicio con el que se comunica. En una aplicação tradicional, probablemente se podrían cablear las ubicaciones, pero en una aplicação de microservicios moderna basada en la nube, este es un problema no trivial. Los servicios de infraestructura, como un agente de mensajes, normalmente tendrán una ubicación estática, que puede especificarse a través de variables de entorno del sistema operativo. Sin embargo, determinar la ubicación de un servicio de aplicação no es tan fácil. Los servicios de aplicação tienen ubicaciones asignadas dinámicamente. Además, el conjunto de instancias de un servicio cambia dinámicamente debido al escalamiento automático y las actualizaciones. En consecuencia, API Gateway, como cualquier otro cliente de servicio en el sistema, necesita utilizar el mecanismo de descubrimiento de servicios del sistema: descubrimiento del lado del servidor o descubrimiento del lado del cliente . Un artículo posterior describirá el descubrimiento de servicios con más detalle. Por ahora, vale la pena señalar que si el sistema usa Client‑Side Discovery, entonces API Gateway debe poder consultar el Registro de servicios , que es una base de datos de todas las instancias de microservicios y sus ubicaciones.
Otro problema que hay que abordar al implementar una API Gateway es el problema del fallo parcial. Este problema surge en todos los sistemas distribuidos siempre que un servicio llama a otro servicio que responde lentamente o no está disponible. La API Gateway nunca debe bloquearse indefinidamente mientras espera un servicio descendente. Sin embargo, la forma en que maneja la falla depende del escenario específico y de qué servicio está fallando. Por ejemplo, si el servicio de recomendaciones no responde en el escenario de detalles del producto, API Gateway debe devolver el resto de los detalles del producto al cliente, ya que aún son útiles para el usuario. Las recomendaciones podrían estar vacías o ser sustituidas, por ejemplo, por una lista de los diez mejores. Sin embargo, si el servicio de información del producto no responde, API Gateway debería devolver un error al cliente.
La API Gateway también podría devolver datos almacenados en caché si estuvieran disponibles. Por ejemplo, dado que los precios de los productos cambian con poca frecuencia, API Gateway podría devolver datos de precios almacenados en caché si el servicio de precios no está disponible. Los datos pueden ser almacenados en caché por la propia API Gateway o almacenados en un caché externo como Redis o Memcached. Al devolver datos predeterminados o datos almacenados en caché, API Gateway garantiza que las fallas del sistema no afecten la experiencia del usuario.
Netflix Hystrix es una biblioteca increíblemente útil para escribir código que invoca servicios remotos. Hystrix agota el tiempo de las llamadas que exceden el umbral especificado. Implementa un patrón de disyuntor que evita que el cliente espere innecesariamente un servicio que no responde. Si la tasa de error de un servicio excede un umbral especificado, Hystrix activa el disyuntor y todas las solicitudes fallarán inmediatamente durante un período de tiempo específico. Hystrix le permite definir una acción alternativa cuando falla una solicitud, como leer desde un caché o devolver un valor predeterminado. Si está utilizando la JVM, definitivamente debería considerar usar Hystrix. Y, si se ejecuta en un entorno que no es JVM, debe utilizar una biblioteca equivalente.
Para la mayoría de las aplicações basadas en microservicios, tiene sentido implementar una API Gateway, que actúa como un único punto de entrada a un sistema. API Gateway es responsable del enrutamiento de solicitudes, la composición y la traducción del protocolo. Proporciona una API personalizada a cada cliente de la aplicación. API Gateway también puede enmascarar fallos en los servicios de backend devolviendo datos en caché o predeterminados. En el próximo artículo de la serie, analizaremos la comunicación entre servicios.
Editor – Esta serie de siete artículos ya está completa:
También puede descargar el conjunto completo de artículos, además de información sobre la implementación de microservicios utilizando NGINX Plus, como un libro electrónico: Microservicios: Desde el diseño hasta la implementación .
Para obtener una visión detallada de casos de uso adicionales, consulte nuestra serie de blogs de tres partes, Implementación de NGINX Plus como API Gateway :
El bloguero invitado Chris Richardson es el fundador del CloudFoundry.com original, una de las primeras PaaS (plataforma como servicio) de Java para Amazon EC2. Ahora asesora a organizaciones para mejorar la forma en que desarrollan e implementan aplicações. También escribe periódicamente sobre microservicios en http://microservices.io .
"Esta publicación de blog puede hacer referencia a productos que ya no están disponibles o que ya no reciben soporte. Para obtener la información más actualizada sobre los productos y soluciones F5 NGINX disponibles, explore nuestra familia de productos NGINX . NGINX ahora es parte de F5. Todos los enlaces anteriores de NGINX.com redirigirán a contenido similar de NGINX en F5.com.