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

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

https://microservices.io

  • 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).