Resumen Completo de Microservicios
246 Visitas 20 minutos Enlace Permanente
Alternativas a las arquitecturas traducionales (monolito y SOA) y que permite un mejor mantenimiento y escalado del sistema
Arquitecturas Tradicionales
- Monolito:
- Todos los componentes se ejecutan en un único proceso de una única máquina.
- Alto acoplamiento entre componentes y clases.
- No comparte nada ni obtiene nada de otras aplicaciones.
- Ventajas:
- Más fáciles de diseñar.
- Tienen mejor rendimiento.
- Problemas:
- No existe el procesado en paralelo.
- Uso muy ineficiente de los recursos.
- Todo debe desarrollarse con la misma plataforma.
- El código suele ser muy grande y complejo (muy difícil de mantener y actualizar).
- Hacer cambios conlleva recompilar y reiniciar el sistema al completo.
- No se pueden comunicar con otras aplicaciones o sistemas.
- SOA:
- Servicios expuestos al público (endpoints) para ser consumidos (SOAP, basado en XML).
- Los servicios exponen metadatos que indican cómo deben consumirse (WSDL).
- Hace uso de ESB (enterprise service bus) como intermediario para autenticación, logs, etc.
- Ventajas:
- Permite compartir datos y funcionalidades.
- Evita la dependencia de plataformas.
- Problemas:
- El ESB suele ser muy complicado y caro.
- El ESB trata de hacer todo (muchas responsabilidades).
- Muy difícil de automatizar tests (se suele hacer a mano).
- Suelen ser bastante más lentos de lo que se piensa.
Arquitectura de Microservicios
Atributos Principales
https://martinfowler.com/articles/microservices.html
- Servicios como Componentes:
- Cada servicio será un componente (en vez de encapsularlos en librerías).
- Sí que se podrá dividir el servicio en librerías y se podrán hacer uso de ellas.
- Permite el despliegue independiente de cada servicio.
- Se tiene que crear una interfaz bien definida.
- Organizado alrededor de las Capacidades del Negocio:
- Cada equipo se hace cargo de un servicio (vertical, en vez de horizontal como en el monolito).
- Cada equipo tiene una visión holística de todo el servicio (manejable, al ser pequeño).
- Cada servicio suele ir asociado a una capacidad que tiene el negocio.
- Permite un rápido desarrollo de los servicios.
- Se tienen que crear unas fronteras bien definidas.
- Productos, no Proyectos:
- El objetivo es desarrollar un producto funcional, no terminar un proyecto.
- Un producto requiere de soporte continuado y relación estrecha con el cliente (no se puede desatender).
- Mejora la satisfacción del cliente.
- Los desarrolladores tienen que mejorar y cambiar su mentalidad.
- Endpoints Inteligentes, Tuberías Tontas:
- Se usan protocolos simples (como HTTP).
- Se usará un gateway o un servicio de descubrimiento de servicios.
- Acelera el desarrollo (menos partes que desarrollar y mantener).
- La aplicación será más sencilla de mantener.
- Gobierno Descentralizado:
- Para cada microservicio se puede elegir la plataforma, BD, sistema de logs, etc.
- Cada equipo es responsable de su microservicio (su desarrollo y mantenimiento).
- Motivación para tomar siempre las mejores decisiones.
- Gestión de Datos Descentralizado:
- Cada microservicio puede tener sus propios almacenes de datos (servicios más modulares).
- Permite tener la mejor herramienta para cada tarea (ej. SQL vs NoSQL).
- Es controvertido y no siempre es posible (ej. transacciones).
- Puede provocar algunos problemas (ej. datos duplicados).
- Automatización de Infraestructura:
- Permite los tests automatizados y el despliegue automático (CI/CD).
- Los ciclos de desarrollo pueden ser muy cortos (incluso de horas o minutos).
- No se puede hacer despliegues manuales.
- Diseñado para Fallar:
- El código asume que puede haber fallos a menudo y debe tratarlos adecuadamente.
- El sistema de monitorización y logs cobra mucha importancia.
- Se definen políticas para hacer reintentos.
- Diseño Evolutivo:
- El paso hacia los microservicios se puede hacer de forma gradual (conviviendo con el legacy).
Problemas que Soluciona
- Plataforma Única: con gobierno descentralizado y gestión de datos descentralizado.
- Despliegue Rígido: con servicios como componentes y automatización de infraestructura.
- Uso Ineficiente de Recursos: con servicios como componentes.
- Grande y Complejo: con servicios como componentes y gestión de datos descentralizado.
- ESB Caro: con endpoints inteligentes (tuberías tontas).
- Falta de Automatización: con automatización de infraestructura.
Desarrollo de Microservicios
Diseño de la Arquitectura
- Componentes:
- En microservicios, los componentes se corresponden con los servicios.
- La división en componentes se suele basar en varios factores:
- Requerimientos de Negocio: casos de uso de área muy concreta del negocio (ej. gestión de pedidos; casos de uso: agregar pedido, eliminar pedido, actualizar pedido, etc.)
- Autonomía Funcional: conjunto de funcionalidades que funcionan de forma independiente.
- Entidades: un servicio por cada entidad o conjunto de entidades muy relacionadas (ej. pedidos).
- Autonomía de los Datos: conjunto de datos que forman una unidad atómica.
- Cuando se necesita datos de varios servicios, existen varias formas de tratarlo:
- Duplicación de Datos: existen datos duplicados en varios microservicios (boundary contexts).
- Peticiones: el servicio solicita al resto los datos que necesita (puede ser lento, acoplamiento).
- Agregación de Servicios: un servicio se encarga de agregar datos de varios (gateway).
- Cross-Cutting: son servicios transversales (logs, caché, usuarios, etc.)
- Comunicaciones:
- 1-to-1 Sync:
- Un servicio llama a otro servicio y espera a que le responda (síncrono).
- Se usa solo cuando se necesitan los datos para continuar el proceso.
- Ventajas: es el más sencillo y tiene un manejo de errores simple.
- Desventajas: puede ser lento y puede provocar que la interfaz se quede bloqueada.
- 1-to-1 Async:
- Un servicio solicita a otro una información pero sigue trabajando hasta que el otro servicio le devuelve la información, momento en el que la tratará.
- Se usa mucho cuando no se necesita una respuesta, tan solo enviar una información.
- Suele implementarse con una “queue” (cola de mensajería, ej. RabbitMQ).
- Ventajas: es rápido y no bloquea la interfaz.
- Desventajas: más difícil de implementar y manejo de errores más complejo.
- Pub-Sub / Event Driven:
- Se define un concentrador donde los servicios pueden informar de acontecimientos y, además, suscribirse (y desuscribirse) para ser informados cuando ciertos acontecimientos ocurren.
- Se usa cuando un servicio necesita notificar a otros varios servicios sobre algo.
- Ventajas: es rápido, no bloquea la interfaz y se comunica con varios servicios a la vez.
- Desventajas: más difícil de implementar, manejo de errores complejo y sobrecargas del sistema.
- Tecnología:
- Almacenamiento de Datos:
- BD Relacional (RDBMS): tablas, columnas fijas, FKs, transacciones.
- NoSQL: escalabilidad y rendimiento, sin esquema fijo, datos en formato JSON.
- Caché: datos en memoria para acceso rápido, objetos serializables.
- Object Storage: datos no estructurados (ej. documentos). [Blob Storage, AWS S3, Minio]
- Lenguajes:
Tipos de Aplicaciones |
Tipado |
Plataformas |
Comunidad |
Rendimiento |
Aprendizaje |
|
.Net Core |
Web, API, Consola, Servicio |
Estático |
Todas |
Grande |
Genial |
Largo |
Java |
Todas |
Estático |
Todas |
Enorme |
Normal |
Largo |
Node.js |
Web, API |
Dinámico |
Todas |
Grande |
Genial |
Medio |
PHP |
Web, API |
Dinámico |
Todas |
Grande |
Regular |
Medio |
Python |
Todas |
Dinámico |
Todas |
Enorme |
Regular |
Corto |
- Diseño:
- Mismos patrones de diseño que el resto de software (design patterns, clean code, etc.)
- Se basa en el patrón de arquitectura de n-capas, pero distribuidas (clean architecture, DDD, TDD, BDD).
Despliegue
- CI/CD:
- Implementación continua y despliegue continuo de forma automática (varias veces al día).
- Pipeline: secuencia de acciones a ejecutar (build, tests, staging, production).
- Docker:
- Empaqueta todo el software en una máquina virtual ligera, fácil y rápida de montar (automatizado).
- Tan solo hay que copiar el contenedor en el servidor, no habrá diferencias entre desarrollo y producción.
- Kubernetes:
- Gestión automatizada de contenedores (cientos o miles).
- Automatización de despliegue, escalado (vertical y horizontal), enrutado, monitorización, balanceo, etc.
Tests
- Particularidades:
- Un test puede empezar en un microservicio y terminar en otro (o varios otros).
- Puede que un tercer servicio necesario no esté disponible aún.
- Los tiempos de los tests pueden ser mayores debido a las comunicaciones.
- Unit Tests (Unitarios):
- Solo comprueban un método en un único proceso, luego son fáciles, rápidos y automatizados.
- Son creados por los mismos desarrolladores (TDD).
- No se diferencian en nada a las pruebas unitarias en otras arquitecturas.
- Hacer UTs solo de los métodos más críticos.
- Integration Tests (Integración):
- También comprueban un método, pero enfocado a comprobar el flujo completo y no solo el código.
- Son más complejos y más lentos, y también deben ser automatizados.
- Son creados por el equipo de calidad (QA) y no por los desarrolladores.
- Los servicios que use el testeo se sustituyen por fakes, stubs o mocks.
- Son los tests más importantes y es donde debe centrarse la mayoría de los esfuerzos.
- End-to-End Tests (Aceptación):
- Cada test comprueba un caso de uso al completo, comprobando solo el estado final (no el flujo).
- Son muy complejos y lentos, y se deben automatizar en la medida de lo posible (no siempre se puede).
- Solo suelen comprobar los escenarios principales y no los atípicos (ya que tardan mucho).
- También son creados por el equipo de calidad (QA) y no por los desarrolladores.
Service Mesh (Cross-Cutting)
- Problemas:
- Hay muchas comunicaciones entre servicios.
- Hay que tener en cuenta problemas de timeouts, seguridad, reintentos, monitorización, etc.
- Mesh:
- Es el componente (proxy) que se encarga de la comunicación entre servicios.
- Se encarga de:
- La conversiones entre protocolos (adapter, cuando el servicio de destino no es un API REST).
- Seguridad en las comunicaciones y fiabilidad (timeouts, reintentos, etc.)
- Autenticación y autorización.
- Monitorización.
- Descubrimiento de servicios.
- Pruebas.
- Balanceo de carga.
- Circuit Breaker: patrón que permite saber si un servicio está activo o no y actuar en consecuencia.
- Arquitectura:
- Cada servicio tiene su mesh (Data Plane).
- Un servicio llamado Control Plane se encarga de gestionar todos los data plane.
- Al conjunto compuesto por el control plane y todos los data planes se le denomina Service Mesh.
- Tipos de Service Mesh:
- In-Process: el data plane está desarrollado dentro de cada servicio (más rápido pero más acoplado).
- Sidecar: el data plane está desarrollado fuera de cada servicio (proxy, menos acoplado pero más lento).
- Productos: istio (más popular), linkerd, maesh, dds (in-process).
Logs y Monitorización
- Logging:
- Guarda la actividad del sistema para realizar auditorías y documentar errores y excepciones.
- Simple: cada servicio tiene su log (están separados, formatos diferentes, falta de visión holística).
- Servicio de Logging: centralizado (Serilog en .NET, Winston en NodeJS) tras queue (RabbitMQ, Kafka).
- Datos: timestamp, user, severity, service, message, stack trace y correlation (id del flujo).
- Productos: ELK Stack (más popular), splunk.
- Monitoring:
- Muestra la actividad del sistema (métricas en dashboards) donde se configuran alertas.
- Tipos: infraestructura (CPU, RAM, disco, red, etc.) y aplicación (métricas a partir de logs).
- Productos: Nagios, Elastic Stack, New Relic, Application Insights.
Del Monolito a los Microservicios
- Importante: una buena planificación y un buen diseño son críticos.
- Nuevos Módulos:
- Se crean como microservicios en vez de integrarlos en el monolito, como hasta ahora.
- Ventajas: fácil de implementar, mínimos cambios en el monolito.
- Desventajas: enfoque híbrido.
- Módulos Existentes:
- Se van pasando los módulos existentes a microservicios, poco a poco.
- Ventajas: enfoque puro.
- Desventajas: muchos cambios en el monolito, muchos tests anti-regresión.
- Reescritura Completa:
- Cuando no hay forma fácil de modularizar el monolito.
- Ventajas: enfoque puro, sistema moderno.
- Desventajas: mucho diseño y muchos tests.
Consejos
Cuando No Usar Microservicios
- Sistemas Pequeños: mejor usar monolito modular (debe haber al menos 5 servicios).
- Datos Muy Entrelazados: sobre todo si requieren de transacciones complejas.
- Alto Rendimiento: siempre habrá latencia por HTTP, (de)serialización, etc.
- Usar y Tirar: aplicaciones que van a tener una vida útil muy corta.
- Sistemas No Actualizables: por ejemplo, sistemas empotrados (embedded).
Microservicios y Organización
- Ley de Conway: “Cualquier organización que diseña un sistema producirá un diseño cuya estructura es una copia de la estructura de comunicaciones de la organización”.
- Equipos Tradicional:
- División horizontal de los equipos: front-end, back-end, DBA y sistemas IT.
- Problemas con microservicios:
- No se trabaja con proyectos sino con productos.
- No hay un responsable claro de cada servicio.
- Nadie tiene una visión holística de todo el servicio.
- El Equipo Ideal:
- Cada servicio tendrá un equipo encargado de desarrollar todo.
- Tamaño: entre 3 y 7 (regla de las 2 pizzas).
- Mentalidad: aprendizaje (continuo), entrenamiento, flexibilidad.
Antipatrones y Errores Comunes
- Mentalidad de Proyecto: creer que una vez desarrollado, puede ser desatendido (no es un proyecto, es un producto).
- Servicios Pobremente Definidos:
- No se le da suficiente importancia al diseño de servicios (componentes).
- Minimonolito: los servicios terminan teniendo demasiadas responsabilidades, con un alto acoplamiento.
- Cambiar el diseño de los servicios (componentes) es muy complicado.
- API Pobremente Definida:
- No cumplen los estándares, siendo complejo de entender y usar.
- No tienen una única responsabilidad, no son consistentes y no tienen versiones.
- No son independientes de la plataforma.
- Cross-Cutting Al Final:
- Se deja para el final servicios que van a ser usados por el resto de servicios (logs, caché, usuarios, etc.)
- Se deben implementar al principio de todo.
- Traspaso de Fronteras:
- Servicios que comienzan a realizar tareas que corresponden a otros servicios (por pereza).
- Existen varias formas de hacer lo mismo, repartido en varios servicios, con alto acoplamiento.
Seguridad
Modelado de Amenazas
- Problemas: pérdida de datos, fuga de datos, inconsistencia de datos, interrupción del servicio.
- Responsables:
- CTO: asegurarse de que todos tienen el cuenta la seguridad.
- CSO: establecer las estrategias de seguridad (también puede hacerlo el CTO).
- Arquitectos: diseñar arquitecturas seguras.
- Servicios IT: implementar la seguridad a nivel de infraestructura y plataforma.
- Jefe de Proyecto: asegurarse de que su equipo tiene en cuenta la seguridad.
- Jefe de Desarrollo: entrenar a los desarrolladores en temas de seguridad.
- Desarrolladores: escribir código seguro.
- Calidad: probar la seguridad del sistema.
- Objetivo: detectar todas las amenazas, determinar cómo mitigarlas, como probarlo y documentarlo todo.
- Cúando Modelar:
- Al principio del proyecto, una vez se tienen los requerimientos.
- Después de un gran cambio (una versión mayor).
- Justo después de un incidente de seguridad.
- Metodología STRIDE: spoofing, tampering, repudiation, information disclosure, denial of service, elevation of privilege (Microsoft, 1999). Alternativas: PASTA, DREAD, Attack Tree, CVSS.
- Herramientas: Microsoft Threat Modeling Tool (TMT), Threat Dragon (OWASP).