Descubrimiento de Microservicios con Nginx y Consul

En una entrada previa ya traté el enfoque de Microservicios y cómo dividir en servicios de grado más fino, independientes, que exponen un API y que colaboran juntos a través de peticiones HTTP. En esta veremos una solución con Nginx y Consul para el descubrimiento dinámico de microservicios.

Una vez que tenemos unos cuantos microservicios, incluso varias instancias de cada uno para balancear la carga, nuestra atención pasa inevitablemente por conocer dónde están desplegados cada uno de ellos, ya que los mismos pueden “convivir” en el mismo servidor, en diferentes servidores de nuestra infraestructura, o en servicios cloud como el de Amazon. Necesitamos conocer si están o no en ejecución además de su IP y puerto.

La solución pasa por un mecanismo de autoregistro de los microservicios en el momento del despliegue en un catálogo de servicios en “runtime”, una forma de decir: “Estoy vivo y me puedes encontrar en esta IP y este puerto”. En el momento del “undeploy” debería desregistrarse del mismo.

Consul

Consul es un sistema distribuido open source creado por Hashicorp para el registro de servicios y la configuración de los mismos. Provee un API que permite a los servicios el registro/desregistro en su catálogo. Consul provee igualmente de un chequeo constante de la salud de los servicios, marcando aquéllos que no pasan el mismo. El cluster de Consul se compone de diferentes procesos agente que se encuentran ejecutándose en los mismos servidores en los que se localizan los servicios, de manera que cada servicio se registra en el agente Consul de su servidor. Estos procesos agente pueden ejecutarse en modo cliente o en modo Servidor. Se recomienda ejecutar entre 3 y 5 agentes en modo Servidor.

consul-arch-5d4e3623

Cualquier registro/desregistro en un nodo del cluster se propaga por el mismo. Todos los nodos del cluster conocen el catálogo de servicios (sus nombres, direcciones ip y puertos).

Una vez que tenemos un catálogo “runtime” de servicios necesitamos un proxy inverso como Apache, HAProxy o Nginx que enrute las peticiones y balancee la carga entre las distintas instancias de un servicio. Todas las peticiones llegarán a uno o más proxies y éste será el encargado del enrutamiento. El problema a resolver en este escenario es llegar a hacer dinámica la configuración de Nginx, o del proxy que se desee de los expuestos anteriormente.

La configuración de servicios se realiza en un fichero, por lo que si la misma se modifica (modificando el fichero), Nginx debería recargarse y leer la nueva. Pero, ¿quién se encarga de reescribir la configuración de Nginx cuando el catálogo de Consul recibe un alta o una baja de un servicio?

Consul-Template

Consul-Template es un proceso que se ejecuta en uno de los nodos del cluster de Consul (mismo servidor que uno de los agentes Consul) y es capaz de escribir en un fichero del File System los cambios en el catálogo de servicios a través de una plantilla. Esta plantilla la transforma en un fichero de configuración en disco y cuando finaliza puede ejecutar un comando del sistema, forzando a nginx a recargar la configuración.

$ consul-template \
  -consul my.consul.internal:6124 \
  -template "/tmp/nginx.ctmpl:/var/nginx/nginx.conf:service nginx restart"

Con el comando de arriba se ejecuta el proceso que estará ejecutándose en segundo plano consultando al agente Consul que indicamos en el parámetro -consul. El parámetro -template indica que la plantilla para el rendering del fichero se encuentra en /tmp/nginx.ctmpl y sobrescribe la configuración de nginx en /var/nginx/nginx.conf. Una vez sobreescrito el fichero se ejecuta el comando que recarga la configuración de Nginx, service nginx restart, en el ejemplo de arriba.

All together

En  el siguiente esquema observamos todos los componentes unidos y colaborando tal y cómo se ha expuesto más arriba.

registroServicios

Arquitecturas de este tipo son fáciles de implementar y distribuir incluso si nos vamos a una infraestructura basada en contenedores docker. El sistema es escalable y de alta disponibilidad con la inclusión de varios nodos con Nginx y Consul-Template.

Microservicios – Introducción: ¿Están las empresas preparadas?

Es difícil que no hayas escuchado antes el término Microservicio, e incluso puede ser que hayas entrado en esta página buscando información sobre ello. Se trata de un término muy en boga en la actualidad, aunque también escucharás hablar de “Arquitectura de microservicios” o de que una aplicación sigue dicha arquitectura.

Definición

Cuando hablamos de microservicios nos referimos a un enfoque orientado a sistemas distribuidos que promueven el uso de servicios de grado más fino, con sus propios ciclos de vida, que colaboran juntos a través de peticiones HTTP a sus API.

Debido a que los microservicios se modelan en torno a los dominios de negocio, se evitan los problemas de arquitecturas en capas y monolíticas tradicionales.

Además cada microservicio es independiente y su código debe ser desplegado sin afectar a los demás. Cada uno de ellos puede escribirse en el lenguaje de programación más adecuado, ya que sólo exportan la API.

Ventajas

Los microservicios por tanto son un nuevo enfoque de las aplicaciones tradicionales, en las cuales teníamos un servidor ejecutando el código de la aplicación en un archivo war. Cada vez que algún módulo / servicio sufría un cambio, debíamos subir a producción de nuevo todo el código, incluyendo los módulos no modificados. En el caso de que haya un módulo de la aplicación que se encuentre saturado de peticiones y queramos balancear la carga, es necesario replicar toda la aplicación en otro servidor.

Frente al enfoque tradicional y en vez de tener un único ejecutable, cada servicio se ejecuta en su propio proceso, comunicándose entre si mediante llamadas a sus respectivas API. Cada microservicio, por tanto se puede desplegar de forma autónoma, de manera que dicho despliegue no afecta a los demás microservicios. Son más fáciles de escalar ya que en vez de replicar toda la aplicación, lo haremos sólo de los microservicios con más carga.

microservicios-fowler

Otras ventajas de esta arquitectura es que se reduce el “Time to market” debido a que evita retrasos en la integración de la nueva funcionalidad en la aplicación monolítica. No hay unanimidad sobre esto, ya que diferentes autores indican que debido a la naturaleza distribuida de la aplicación el time to market será mayor. A continuación se enumeran las ventajas de este enfoque:

  • Los servicios son muy simples, enfocados en hacer una cosa y hacerla bien. Algunos autores aseguran que Microservicios es SOA bien hecho.
  • Cada servicio puede ser construido utilizando la mejor herramienta y la más apropiada para el trabajo que va a realizar.
  • Se trata de sistemas débilmente acoplados.
  • Múltiples desarrolladores y equipos pueden realizar entregas de manera independiente.
  •  Facilita la entrega continua, permitiendo lanzamientos frecuentes, manteniendo el resto del sistema disponible y estable.

Desventajas

Pero no todo son ventajas y un sistema basado en Microservicios posee una complejidad añadida:

  • Un gran número de microservicios son difíciles de orquestar.
  • Dificultad para gestionar y realizar test de las dependencias.
  • Aplicación no uniforme. Poder elegir entre diferentes tecnologías conlleva diseños de aplicación y arquitectura no uniformes, lo que puede incrementar el coste de mantenimiento a largo plazo.
  • Complejidad DevOps. Es necesario tener un equipo Dev Ops maduro para manejar la complejidad en mantener aplicaciones basadas en microservicios.
  • Incremento del uso de recursos. La inversión inicial para ejecutar estas aplicaciones es alto, debido a la ejecución independiente de cada componente en su propio proceso o contenedor de ejecución (más RAM y CPU).
  • Incremento de la comunicación por la red. Este sistema requiere conexiones confiables y rápidas.
  • Marshalling – Unmarshalling. Cuando un servicio requiere datos de otro, el llamante encapsula los datos en algún estándar desde su representación interna, mientras que el llamado realiza una la operación contraria para operar con dichos datos. Esto requiere más procesamiento en comparación con una arquitectura de aplicación convencional.
  • Seguridad en la red. La comunicación entre servicios necesita ser securizada para evitar brechas de seguridad. Debido a la composición de diferentes módulos “movibles”, estas aplicaciones son más vulnerables en cuanto a seguridad.
  • Testing. Incremento de la complejidad para realizar testing de estas aplicaciones en comparación con aplicaciones monolíticas.
  • Monitorización en producción. El coste de monitorizar esta aplicación es mayor y la no disponibilidad de las herramientas adecuadas es un tema a ser considerado.
  • Logs y trazas. nos encontramos con una fuente inagotable de logs generados por cada uno de los procesos, por los contenedores que ejecutan los microservicios y por el propio servidor físico o virtual.
  • Transaccionalidad en las operaciones. Los microservicios por naturaleza son “stateless, por lo que se ve la necesidad de una tercera capa de persistencia y gestión de la transaccionalidad.

implement-microservices

Conclusiones

Se trata de un enfoque que no es nuevo pero en el que muchas empresas están poniendo el foco debido a la complejidad a la que han llegado sus aplicaciones empresariales. La Arquitectura de microservicios no es para todo el mundo pero se adapta perfectamente a aplicaciones enterprise o proyectos que seguro van a escalar. La velocidad gana en el mercado y la idea de Microservicios es ganar en velocidad, pero también supone cambios en la empresa, empezando por integrar primero DevOps y herramientas de DevOps en la misma. ¿Están las empresas preparadas para dar el paso a Microservicios?