Microservicios y Gestión de Datos (Separando Responsabilidades)
Cuando comencé a trabajar con microservicios, interpreté la regla común de "dos servicios no deben compartir una fuente de datos" demasiado al pie de la letra.
Lo leí en todas partes: "no debes compartir una base de datos entre dos servicios". Y sí, tiene sentido buscar un cierto nivel de aislamiento e independencia entre los microservicios.
Pero también existe la necesidad de mantener coherencia y facilitar el acceso compartido a ciertos datos cuando sea necesario, así es que en este artículo vamos a explorar los distintos enfoques para gestionar datos entre microservicios.
Veremos que una opción híbrida suele ser la mejor solución para balancear la independencia con las necesidades de negocio, también daré algunas pautas para determinar la separación apropiada entre servicios y sus orígenes de datos, porque mucho se habla de microservicios, pero es muy claro hasta que punto se deberian separar las responsabilidades.
Entendiendo el concepto de Microservicios
Los microservicios en el mundo de la programación, son como bloques de LEGO, donde cada bloque representa un servicio independiente que cumple una función específica. Juntos, estos bloques forman una estructura compleja, al igual que diferentes microservicios juntos componen una aplicación completa.
La encrucijada de los datos
Pongamos un ejemplo simple para entender mejor el dilema. Supongamos que estás construyendo un sistema de biblioteca. Tienes un microservicio para gestionar los libros, otro para los usuarios y otro para los préstamos. Cuando un usuario toma prestado un libro, el microservicio de préstamos necesita información tanto del libro como del usuario.
Determinando la separación de los Microservicios
Una pregunta clave al diseñar la arquitectura de microservicios es cómo determinar cuáles servicios deben estar separados y cuáles pueden combinarse y no tengo una respuesta clara para ello, ya que depende de muchos factores, entre ellos el tamaño del equipo, el presupuesto y la complejida del proyecto, pero he descubierto algunas pautas que podrían ayudar a determinar el cuando crearlos:
-
Funcionalidades muy distintas: Cada microservicio debería tener una única responsabilidad. Por ejemplo, en una aplicación de biblioteca, la gestión de préstamos y la administración de libros y usuarios tienen propósitos claros y diferentes. Mientras que el primero se encarga de la logística de préstamo y devolución, el segundo se centra en catalogar y mantener la información de los libros y los usuarios. Esta distinción clara justifica la separación.
-
Diferentes ciclos de cambio: Si un segmento de tu aplicación se actualiza frecuentemente (por ejemplo, una interfaz de usuario) mientras que otro segmento permanece bastante constante (como una base de datos de registros históricos), es prudente separarlos. Esto permite que las actualizaciones no interrumpan todo el sistema.
-
Escalabilidad distinta: Algunas partes de tu aplicación pueden experimentar más tráfico que otras. Si anticipas que una función tendrá un alto volumen de solicitudes, podría ser útil separarla para que pueda escalarse de forma independiente sin afectar a otros servicios.
-
Cambios simultáneos: Si dos funciones suelen actualizarse al mismo tiempo, podría tener sentido mantenerlas juntas. Por ejemplo, si en un ecommerce decides agregar una nueva característica a un producto, es probable que quieras actualizar tanto el catálogo como el precio al mismo tiempo.
-
Restricciones regulatorias o de seguridad: Las regulaciones, especialmente en áreas como finanzas o salud, pueden requerir que ciertos datos se manejen de maneras específicas. Si una parte de tu aplicación maneja datos sensibles que tienen estrictos requisitos de cumplimiento, puede ser útil aislar esa parte en un microservicio separado.
-
Equilibrio en la granularidad: Mientras que los microservicios deben ser lo suficientemente pequeños como para manejar una función específica, no conviene exagerar y fragmentar excesivamente la aplicación. El equilibrio es clave: si te encuentras manejando microservicios que solo tienen unas pocas líneas de código, puede que haya llegado el momento de reconsiderar si esa división tiene sentido.
Como vemos hasta ahora, no hay una única respuesta correcta, definir los servicios y bases de datos requiere un análisis de los distintos aspectos del negocio y la aplicación.
Ventajas y Desafíos de Fuentes de Datos Independientes
Al adoptar una arquitectura de microservicios, una decisión crucial es determinar cómo se gestionarán los datos entre estos servicios. Una opción es que cada microservicio tenga su propia fuente de datos independiente, pero habrán algunos desafíos.
Ventajas
-
Aislamiento: Si un microservicio sufre algún fallo o necesita mantenimiento, este no afecta directamente a los otros servicios. Por ejemplo, si el servicio de usuarios necesita una actualización, el servicio de préstamos puede seguir operando sin interrupciones.
-
Seguridad y Control: Cada microservicio tiene control total sobre su propia base de datos. Esto reduce el riesgo de acceso no autorizado y permite implementar medidas de seguridad específicas según la naturaleza de los datos que maneja cada servicio.
-
Optimización y Flexibilidad: Al ser independiente, cada base de datos puede ser optimizada según las necesidades específicas del microservicio. Si el servicio de usuarios tiene un volumen masivo de registros pero el servicio de préstamos no, cada uno puede elegir una estructura de base de datos que mejor se adapte a su carga.
Desafíos
-
Consistencia de Datos: La coherencia entre microservicios se convierte en un reto. Por ejemplo, si un usuario actualiza su dirección en su perfil (manejado por el servicio de usuarios), el servicio de préstamos necesita reflejar este cambio cuando envía notificaciones o estados de cuenta a dicho usuario.
-
Complejidad en la Comunicación: Los microservicios necesitan comunicarse entre sí para mantenerse actualizados. Esto puede llevar a una red intrincada de llamadas y respuestas, lo que puede complicar la trazabilidad y el diagnóstico de problemas.
-
Redundancia de Datos: A veces, cierta información necesita estar presente en más de un microservicio. Por ejemplo, mientras que la información detallada de un usuario se guarda en el microservicio de usuarios, el microservicio de préstamos también podría necesitar guardar algunos detalles básicos, como el nombre del usuario, para hacer más eficientes sus operaciones. Esto puede llevar a la duplicación de datos.
Conexiones entre Microservicios
Aquí es donde entra en juego el enfoque híbrido, que combina lo mejor de ambos mundos. En lugar de mantener fuentes de datos completamente separadas o compartidas, permitiendo que los microservicios tengan su propio origen de datos y, además, accedan de forma de solo lectura a los datos de otros servicios. Es crucial mantener conexiones separadas para cada acceso, garantizando así un correcto funcionamiento y seguridad.
El Enfoque Híbrido
Al implementar una arquitectura de microservicios, es fundamental garantizar que cada servicio pueda acceder y procesar la información necesaria sin sacrificar la independencia. Un enfoque que me ha ayudado en situaciones complejas, como nuestra aplicación de biblioteca, es el híbrido, te explico como sería:
Estructura de la Biblioteca
En el contexto de nuestra biblioteca:
-
El microservicio de Libros posee su base de datos independiente. Aquí es donde se almacena y se administra todo lo relacionado con los títulos, autores, ediciones, entre otros detalles. Cuando se agrega o edita un libro, se refleja directamente en esta base.
-
El microservicio de Préstamos, por su parte, mantiene un registro de todos los préstamos que se han realizado. Pero este no es un servicio aislado: necesita información sobre qué libro se ha prestado y a qué usuario. Por ello, aunque tiene su base de datos principal para préstamos, establece conexiones de solo lectura con las bases de Libros y Usuarios. Esto le permite, por ejemplo, verificar la disponibilidad de un libro o asegurarse de que un usuario no exceda su límite de préstamos. Todo esto sin necesidad de consultar a los otros microservicios.
Es crucial destacar que aunque Préstamos accede a las bases de Libros y Usuarios, no tiene la capacidad de modificar los datos en esas bases. Esto asegura que cada microservicio mantiene la soberanía sobre su dominio principal. Y para ello, en escenarios donde los microservicios comparten una misma base de datos física pero están lógicamente separados, se pueden crear diferentes usuarios con permisos específicos para acceder a diferentes tablas. Sin embargo, en arquitecturas más puras de microservicios, cada servicio tendría su propia base de datos independiente.
Comunicación Directa entre Microservicios
Una de las formas más comunes de interacción entre microservicios es a través de llamadas HTTP, que esencialmente es una solicitud directa de un servicio a otro. En nuestra arquitectura híbrida, esto se traduce en la capacidad de un microservicio para solicitar información o notificar cambios a otro microservicio de manera directa.
Usando nuestro ejemplo de la biblioteca:
-
Solicitud de Información: Imagina que el microservicio de Préstamos necesita información sobre un libro en particular antes de procesar un préstamo. En lugar de tener una copia propia de todos los detalles del libro, puede enviar una solicitud HTTP directamente al microservicio de Libros para obtener la información necesaria.
-
Notificaciones de Cambios: Siguiendo el mismo ejemplo, si un usuario actualiza su dirección de correo electrónico en el microservicio de Usuarios, este servicio podría notificar al microservicio de Préstamos mediante una llamada HTTP, informándole del cambio. De esta manera, el servicio de Préstamos puede actualizar su registro y asegurarse de que las notificaciones sobre préstamos se envíen al correo correcto.
-
Ventajas y Consideraciones: Esta forma de comunicación es directa y, a menudo, más rápida que otros métodos. Sin embargo, también introduce ciertos desafíos. Es importante asegurarse de que los servicios estén disponibles y que las llamadas HTTP estén protegidas para evitar posibles brechas de seguridad. Además, hay que considerar el rendimiento y asegurarse de que el sistema pueda manejar la carga de múltiples solicitudes simultáneas, especialmente en sistemas de alto tráfico.
Ojo, no estoy diciendo que las llamadas HTTP entre microservicios son las más efectivas, ya que existen diferentes mecanismos de comunicación, esta simplemente es la más sencilla y como con cualquier técnica, es esencial implementarla de manera cuidadosa y considerada, teniendo en cuenta la seguridad, la disponibilidad y el rendimiento.
Beneficios del Enfoque Híbrido
Adoptando esta estructura, obtenemos lo mejor de ambos mundos:
-
Independencia de Servicios: Cada microservicio opera y mantiene su base de datos principal sin interferencias externas.
-
Acceso Eficiente a la Información: Los servicios pueden acceder a la información de otros cuando es esencial para su funcionamiento, pero siempre en un modo que no compromete la integridad de los datos.
-
Actualización Asíncrona: A través de los eventos, los servicios se mantienen informados sobre los cambios relevantes, permitiendo una coherencia eventual. Es decir, aunque no se actualizan en tiempo real, con el tiempo todos los microservicios reflejarán la realidad más actual de los datos.
Con esta estructura híbrida, conseguimos un sistema flexible, eficiente y resiliente, capaz de adaptarse a las necesidades cambiantes de una biblioteca moderna.
Buscando el Equilibrio
Los microservicios ofrecen ventajas incomparables en términos de escalabilidad y flexibilidad, pero, como con muchas cosas en el desarrollo de software, la gestión de datos requiere un equilibrio cuidadoso entre autonomía y coherencia.
El enfoque híbrido propone una solución pragmática que permite que los microservicios mantengan su independencia al tener sus propias fuentes de datos, pero también accedan en modo de lectura a otros servicios cuando sea necesario. Es vital tener en cuenta las implicaciones de seguridad, garantizando configuraciones adecuadas tanto en la comunicación entre microservicios como en la estructura de los datos..
Dependiendo de la infraestructura y las necesidades del proyecto, los microservicios podrían compartir una base de datos física pero estar lógicamente separados mediante diferentes usuarios y permisos. O, en configuraciones más separadas, cada microservicio tendría su propia base de datos física.
Este camino creo que es una amalgama de teoría y práctica, desarrollar microservicios que funcionen realmente bien toma tiempo y siempre se puede aprender y mejorar, este artículo es parte de mis reflexiones y las lecciones aprendidas, mismas que me han ayudado a construir aplicaciones más resilientes y eficientes.
Si tienen experiencias o enfoques diferentes en la gestión de microservicios, ¡me encantaría escucharlos! La comunidad crece y se fortalece con el intercambio de ideas.
Happy coding! :D
Photo by Vanessa Bucceri on Unsplash