Arquitectura basada en microservicios Parte 2

  • En el post Arquitectura de Microservicios Parte 1 estuvimos viendo un modelo arquitectónico de referencia para una un sistema que siga el nuevo estilo arquitectural basado en microservicios.
  • Ahora, en este segundo post vamos a ver cuál podría ser uno de los muchos modelos de implementación.
  • Continuemos pues con la segunda parte de esta serie…

1 MODELO DE IMPLEMENTACIÓN

  • Una vez definidos los componentes operacionales que intervienen en el modelo arquitectónico de referencia, vamos a ver con qué tecnologías podemos implementar cada uno de los mismos y cuáles son las que consideramos más adecuadas para cada componente.
  • Como hemos avanzado anteriormente, los microservicios se despliegan en unidades independientes y se ejecuta cada uno en un proceso distinto.
  • Las aplicaciones monolíticas usan los clásicos servidores de aplicaciones JEE (JBoss AS, WAS) para su ejecución, usando unidades o recursos de despliegue estándar como los EAR o WAR, pero existen otros mecanismos más actuales y ligeros que permiten crear también un microservicio como un proceso java ligero.
  • Respecto al resto de componentes que forman parte del modelo arquitectural que hemos definido, vamos a pasar a ver qué implementación podemos usar en cada uno de ellos.
  • Como recomendación, en base a mi experiencia en Spring y dado que se trata tecnologías Open Source con un grado de madurez mayor que otras, recomendamos basarnos en la familia de spring.io y en componentes Open Source de Netflix (OSS) para implementar todos los componentes del modelo de referencia descritos en la primera parte del post.
Componente Spring Cloud y OSS Netflix
Servidor de configuración central Spring Cloud Config o Netflix Achaius integrado con Spring, que permite recarga en caliente
Servicio de descubrimiento Netflix Eureka
Enrutamiento dinámico y balanceador de carga Netflix Ribbon
Circuit Breaker Netflix Hystrix
Monitorización Netflix Hystrix Dashboard y Turbine
Análisis centralizado de log Elasticsearch, Logstash, Kibana (ELK)
Servidor Perimetral Netflix Zuul
APIs de protección basadas en estándar OAuth Spring Cloud + Spring Security OAuth
Microservicio Spring Boot , Spring Cloud Data Flow , Spring Cloud Stream, Librerias comunicación con backends
Infraestructura de comunicación asíncrona RabbitMQ

1.1 Servidor de configuración

  • Spring Cloud Config proporciona soporte para configuraciones cliente y servidor en entornos distribuidos.
  • Proporciona un servidor de configuración central para el manejo de propiedades externas para las aplicaciones a través de todos los entornos.
  • El concepto que maneja de configuración en cliente y en servidor encaja muy bien con aplicaciones desarrolladas en Spring (Environment y PropertySource)
  • Puede manejar las configuraciones de los microservicios desde los entornos de desarrollo y test hasta producción y asegurarse que tienen toda la configuración necesaria cuando se migran.
  • Se integra con Git de forma natural y es fácilmente extensible mediante plugins.
  • Como alternativa a Spring Cloud Config, existe un OSS de Netflix que se denomina Archaius, que tiene la particularidad de que permite transmitir “en caliente” los cambios que se produzcan en la configuración.
  • Archaius se integra también fácilmente con aplicaciones en Spring.

1.2 Servicio de descubrimiento

  • Netflix Eureka permite a los microservicios registrarse por sí mismos en el momento en el que arrancan.
  • Su base es un servidor REST que se usó en AWS cloud para localizar servicios para el balanceo de carga y tolerancia a fallos en la capa middleware.
  • En Netflix se usa además de lo anterior para otras tareas de despliegue con el objetivo de evitar la propagación de nuevas versiones a todas las instancias en caso de problemas, de “rollback” rápido de las versiones, de descubrimiento de instancias de cache en memoria etc…
  • Aparte del Servidor Eureka, también Eureka proporciona un cliente Eureka basado en Java que hace más fácil las interacciones con el servidor.
  • El cliente proporciona balanceo básico del tipo “round-robin”.
  • Se integra fácilmente con Spring Cloud, vía anotaciones.

  • Como alternativa estaría AWS ELB, pero Eureka es más sencillo (no tiene proxy y el balanceo se realiza a nivel de instancia), es también fácil de extender y no usa Sticky Sessions, lo cual encaja mejor en el uso de microservicios que no mantienen estado.

1.3 Balanceador y enrutador dinámico

  • Netflix Ribbon proporciona una librería IPC (Llamadas entre procesos) que ha sido probada exhaustivamente en entornos Cloud y proporciona las siguientes características:
    • Balanceo en el cliente
    • Tolerancias a fallos
    • Múltiples protocolos (HTTP, TCP, UDP) en modelo asíncrono y reactivo.
    • Cacheo y procesamiento diferido
  • Se integra perfectamente con Eureka, de hecho usa el API cliente de Eureka para obtener dinámicamente la lista de servidores Eureka.
  • Se integra fácilmente con Spring Cloud, vía anotaciones.

1.4 Circuit Breaker

  • Netflix Hystrix es una librería que añade tolerancia a la latencia y tolerancia a fallos a nuestro entorno, en este caso a nuestro sistema o paisaje de microservicios.
  • Ayuda de hecho a controlar las interacciones entre las instancias de microservicios distribuidas.
  • Hystrix hace esto aislando puntos de acceso entre los servicios y parando los fallos en cascada entre ellos, lo cual aumenta la resistencia del sistema.
  • Hystrix está diseñado para hacer lo siguiente:
    • Dar control sobre la latencia y fallos de las dependencias entre servicios
    • Parar los fallos en cascada en el sistema.
    • Recuperación rápida ante los fallos.
    • Monitorización en tiempo real
  • Hystrix se ejecuta embebido dentro del consumidor del servicio.
  • Se integra fácilmente con Spring Cloud, vía anotaciones.

1.5 Monitorización

  • Netflix Hystrix Dashboard puede ser usado para proporcionar una vista (a través de su panel de control) de los circuits breakers
  • Netflix Turbine puede, basándose en la información de Eureka, agregar al panel de control toda información de todos nuestros microservicios, con lo cual tenemos una vista conjunta de los mircroservicios con su circuit breaker, como puede verse en la siguiente imagen:

  • Turbine puede ser usado con cualquier fuente de datos que soporte el formato JSON. Sin embargo, está especializado para agregar streams de salida de Hystrix.
  • Se integra fácilmente con Spring Cloud, vía anotaciones.

1.6 Análisis centralizado de log

  • Para la recolección de todas las trazas que producen los componentes de nuestro sistema y su análisis centralizado, uno de los stacks más usados es el denominado ELK (Elasticsearch, Logstash, Kibana)

  • ELK está compuesto de 3 componentes:
    • Logstash: Es un agente que se encuentra en cada uno de nuestros componentes y que se dedica a “cosechar” trazas de los mismos. Su trabajo es leer trazas, normalizarlas, estructurarlas y mandarlas al cluster de elasticsearch.
    • Elasticsearch: Es un almacén distribuido de datos indexados que normalmente corre como un simple cluster. Su trabajo es almacenar de una forma fiable las trazas a través de los nodos del cluster y servir la consultas a Kibana.
    • Kibana: Es un servidor web que proporciona un interfaz gráfico web. Su trabajo es permitir construir vistas gráficas de las trazas basadas en las consultas de Elasticsearch. Se pueden hacer agregaciones complejas de datos con rangos de tiempo, etc…

  • Otras alternativas a ELK, pero con menos posibilidades sería el uso de la imagen de Docker Loggy (que usa el demonio rsyslog) o logspout

1.7 Servidor Perimetral

  • Netflix Zuul es por supuesto nuestro “guardián” de la puerta al mundo exterior, de hecho, su nombre Zuul proviene del personaje “guardián de la puerta” de la peli de los Cazafantasmas.
  • No permite que ninguna petición externa no autorizada pase a través de él.
  • Proporciona un punto de entrada bien conocido a los microservicios de nuestro sistema.
  • Usa puertos dinámicamente repartidos para así evitar conflictos y minimizar la administración.
  • Zuul usa Ribbon para buscar servicios disponibles y enrutar las peticiones a los mismos a la apropiada instancia que las atienda.
  • Zuul proporciona un montón de filtros para realizar funciones de:
    • Monitorización de peticiones
    • Enrutado dinámico
    • Pruebas de estrés
    • Manejo de respuestas estáticas
    • Mecanismo de Throttling o Load Shedding
    • Enrutado a través de regiones (AWS Regions)
  • Como alternativa se podría usar soluciones basadas en WebSeal de IBM, pero se alejan de la integración con el resto de componentes de Netflix y no son Open Source.

1.8 APIs de protección basadas en OAuth

  • La protección de nuestros microservicios no requiere de nada extra o distinto a nuestras aplicaciones monolíticas, con lo que nuestra recomendación es seguir el estándar Oauth 2.0.
  • Aquí, Spring Cloud Security proporciona todo lo necesario para implementar este protocolo necesario para securizar los microservicios API.
  • En este caso el Servidor Perimetral actúa como mero transmisor del token de acceso que mandan los consumidores hasta el servidor de recursos.
  • También es necesario contar con un Servidor de autorización OAuth y clientes OAuth en consumidor. Todos ellos implementados mediante Spring Cloud Security.

1.9 Microservicio

  • Como comentamos antes, para implementar los microservicios (que se ejecutan como procesos independientes) proponemos crear procesos Java ligeros.
  • Para ello proponemos usar Spring Cloud y Spring Boot, ya que se integra fácilmente (mediante anotaciones) con el resto de componentes OSS.
  • Spring Boot que tiene como unidad de despliegue un JAR y se lleva muy bien con el uso de contenedores ligeros como Docker u ofertas PaaS como CloudFoundry, Heroku o incluso Oracle Cloud Services.
  • En el artículo de dzone https://dzone.com/articles/java-ee-app-servers-are-they-still-relevant-in-a-w?edition=99051&utm_source=Spotlight&utm_medium=email&utm_campaign=java%202015-11-12 se habla del gran avance del uso de servicios como procesos java ligeros frente al declive de los servidores de aplicaciones cuando se usan contenedores.
  • Al escalar dinámicamente, cada microservicio tendrá menos peticiones concurrentes que en la versión monolítica.
  • Para implementar su interfaz RESTful puede se recomienda hacer uso de Spring MVC y para comunicarse con otros servicios de los “templates” de Spring, como RESTTemplate, WSTemplate, RabbitTemplate y JDBCTemplate.
  • También por su puesto pueden hacer uso de Hibernate u otro ORM para acceder a BBDD relacionales o bien los clientes del API correspondiente para acceder a BBDD NoSQL (por ejemplo Mongo DB, etc…).
  • Los microservicios también pueden implementar soluciones de cache ( EHCahe o Hazelcast) para reducir llamadas y mejorar el rendimiento.
  • Asimismo los microservicios compuestos pueden hacer uso de Spring Data Flow para orquestar a otros microservicios.
  • Spring Data Flow permite procesamiento de streams y batch a través de cloud.
  • Permite a los desarrolladores crear, orquestar y refactorizar “pipelines” de datos que pueden “ingerir” gran cantidad de datos para su análisis en tiempo real o para importaciones y/o exportaciones. Cada elemento de procesa los datos en la “pipeline” puede ser un microservicio.

1.10 Infraestructura de comunicación asíncrona

  • Para mejorar el rendimiento cuando se presenten muchas llamadas entre los microservicios o bien cuando se llaman a backend externos se puede usar un modelo de comunicación asíncrona, con lo que es necesario contar con una infraestructura que permita este modelo.
  • Para ello se puede usar servicios de mensajería como RabbitMQ que propociona colas de alta disponibilidad, clustering, multi-protocol, etc… y una integración bastante avanzada con soluciones Cloud como (EC2, Pivotal Cloud Foundry) y también cuenta con imágenes de Docker.

1.11 Vista de la Arquitectura de Implementación del sistema

Un comentario

Deja un comentario