¿Cuál es el tamaño correcto para un microservicio? Seguramente oirá afirmaciones del tipo "ni demasiado grande ni demasiado pequeño", y aunque esto es ciertamente correcto, no resulta muy útil en la práctica. Pero si se empieza desde un modelo de dominio cuidadosamente diseñado, es mucho más fácil razonar acerca de los microservicios.
En este artículo se usa un servicio de entrega con drones como ejemplo de ejecución. Puede obtener más información sobre el escenario y la implementación de referencia correspondiente aquí.
Desde un modelo de dominio a los microservicios
En el artículo anterior, definimos un conjunto de contextos delimitados para la aplicación Drone Delivery. Luego observamos más de cerca uno de estos contextos delimitados, el contexto delimitado Shipping, e identificamos un conjunto de entidades, agregados, y servicios de dominio para ese contexto delimitado.
Ahora estamos preparados para pasar del modelo de dominio al diseño de la aplicación. Este es un enfoque que puede usar para derivar microservicios desde el modelo de dominio.
Comience con un contexto delimitado. En general, la funcionalidad en un microservicio no debe abarcar más de un contexto delimitado. Por definición, un contexto delimitado marca el límite de un modelo de dominio en particular. Si encuentra que un microservicio mezcla modelos de dominio diferentes, es un signo de que puede que tenga que volver atrás para refinar el análisis de dominio.
A continuación, mire los agregados en el modelo de dominio. Los agregados suelen ser buenos candidatos para microservicios. Un agregado bien diseñado tiene muchas de las características de un microservicio bien diseñado, como:
- Un agregado se deriva de los requisitos empresariales más que de las preocupaciones técnicas, como el acceso a datos o la mensajería.
- Un agregado debe tener alta cohesión funcional.
- Un agregado es un límite de persistencia.
- Los agregados deben tener un acoplamiento flexible.
Los servicios de dominio también son buenos candidatos para microservicios. Los servicios de dominio son operaciones sin estado a través de varios agregados. Un ejemplo típico es un flujo de trabajo que implica varios microservicios. Veremos un ejemplo de esto en la aplicación Drone Delivery.
Por último, tenga en cuenta los requisitos no funcionales. Observe factores como el tamaño del equipo, los tipos de datos, tecnologías, requisitos de escalabilidad, requisitos de disponibilidad y requisitos de seguridad. Estos factores pueden llevarle a volver a dividir un microservicio en dos o más servicios más pequeños, o a hacer lo contrario combinando varios microservicios en uno.
Después de identificar los microservicios en su aplicación, valide el diseño con los siguientes criterios:
- Cada servicio tiene una única responsabilidad.
- No hay llamadas que generen mucha conversación entre servicios. Si dividir la funcionalidad en dos servicios hace que estos generen demasiada conversación, esto puede ser una indicación de que estas funciones deben estar en el mismo servicio.
- Cada servicio es lo suficientemente pequeño como para que un equipo pequeño lo pueda generar trabajando de forma independiente.
- No hay interdependencias que requieran la implementación de dos o más servicios en sincronía. Siempre debe ser posible implementar un servicio sin tener que volver a implementar ninguno de los demás servicios.
- Los servicios no están estrechamente acoplados y pueden evolucionar independientemente.
- Los límites de servicio no causarán problemas con la coherencia de datos o la integridad. A veces es importante mantener la coherencia de datos colocando la funcionalidad en un único microservicio. Dicho esto, considere si realmente necesita una fuerte coherencia. Hay estrategias para resolver la coherencia final en un sistema distribuido, y las ventajas de descomponer servicios generalmente superan los desafíos que supone administrar la coherencia final.
Sobre todo, es importante ser práctico y recordar que el diseño basado en dominio es un proceso iterativo. En caso de duda, empiece con microservicios más generales. Dividir un microservicio en dos servicios más pequeños es más sencillo que la refactorización de funcionalidad entre varios microservicios existentes.
Ejemplo: Definición de los microservicios de la aplicación Dron Delivery
Recuerde que el equipo de desarrollo había identificado los cuatro agregados (Delivery, Package, Drone, y Account) y dos servicios de dominio, Scheduler y Supervisor.
Delivery y Package son candidatos obvios para los microservicios. Scheduler y Supervisor coordinan las actividades realizadas por otros microservicios, por lo que tiene sentido implementar estos servicios de dominio como microservicios.
Drone y Account son interesantes porque pertenecen a otros contextos delimitados. Una opción es que Scheduler llame a los contextos delimitados Drone y Account directamente. Otra opción es crear microservicios Drone y Account dentro del contexto delimitado Shipping. Estos microservicios mediarán entre los contextos delimitados a través de la exposición de las API o los esquemas de datos que son más adecuados para el contexto Shipping.
Los detalles de los contextos delimitados Drone y Account quedan fuera del ámbito de esta guía, por lo que hemos creado servicios ficticios para ellos en nuestra implementación de referencia. Pero hay algunos factores a tener en cuenta en esta situación:
¿Cuál es la sobrecarga de la red al llamar directamente al otro contexto delimitado?
¿Es el esquema de datos para el otro contexto delimitado adecuado para este contexto, o es mejor tener un esquema que se adapte a este contexto delimitado?
¿Es el otro contexto delimitado un sistema heredado? Si es así, podría crear un servicio que actúe como una capa para evitar daños para traducir entre el sistema heredado y la aplicación moderna.
¿Cuál es la estructura del equipo? ¿Es fácil comunicarse con el equipo que se encarga del otro contexto delimitado? De lo contrario, la creación de un servicio que medie entre los dos contextos puede ayudar a mitigar el costo de la comunicación entre equipos.
Hasta ahora, no hemos considerado ningún requisito no funcional. Pensando en los requisitos de rendimiento de la aplicación, el equipo de desarrollo decidió crear un microservicio Ingestion independiente, que se encarga de la ingesta de las solicitudes de cliente. Este microservicio implementará la redistribución de la carga colocando las solicitudes entrantes en un búfer para su procesamiento. Scheduler leerá las solicitudes desde el búfer y ejecutará el flujo de trabajo.
Los requisitos no funcionales llevaron al equipo a crear un servicio adicional. Todos los servicios hasta ahora se han dedicado al proceso de programación y entrega de paquetes en tiempo real. Pero el sistema también necesita almacenar el historial de cada entrega en un almacenamiento a largo plazo para el análisis de datos. El equipo consideró hacer que esto fuera responsabilidad del servicio Delivery. Sin embargo, los requisitos de almacenamiento de datos para el análisis histórico son muy distintos a los de las operaciones en vuelo (consulte Consideraciones de datos). Por lo tanto, el equipo decidió crear un servicio Delivery History independiente que realizará escuchas de eventos DeliveryTracking del servicio Delivery, y escribirá los eventos en un almacenamiento a largo plazo.
En el siguiente diagrama se muestra el proceso en este punto:
Descargue un archivo Visio de esta arquitectura.
Pasos siguientes
Llegados a este punto, debe comprender claramente el propósito y la funcionalidad de cada microservicio del diseño. Ahora puede diseñar el sistema.