Microdot Framework
Microdot es un framework .NET de código abierto que responde a muchas de las necesidades para crear microservicios de forma más sencilla.
Algunas de sus principales características:
- Contenedor de servicios para alojar un microservicio
- RPC entre servicios para una sencilla comunicación de servicios basada en interfaz
- Almacenamiento en caché de respuesta transparente del lado del cliente entre servicios
- Soporte de registro y rastreo distribuido
- Balanceo de carga del lado del cliente y descubrimiento de servicios
- Comprobaciones de estado detalladas para facilitar el seguimiento del servicio
- Sistema de configuración jerárquica con detección de cambios en línea
- Inyección de dependencia
- Integración de Orleans para crear servicios basados en Orleans y disfrutar de los beneficios de los actores virtuales
Detalles
El framework de Microdot permite crear microservicios escalables y confiables (un “chasis de microservicio” ), lo que permite concentrarse en escribir código que defina la lógica del servicio sin la necesidad de abordar la gran cantidad de desafíos de desarrollar un sistema distribuido.
Microdot también funciona muy bien con el marco de actores virtuales de Orleans , lo que le permite escribir microservicios basados en Orleans fácilmente.
Microdot implementa y admite muchos patrones establecidos relacionados con microservicios. A continuación se muestra un diagrama completo creado por Chris Richardson de Microservices.io , con resaltados de color añadidos para mostrar qué partes se implementan en Microdot (amarillo), cuáles se planea implementar (violeta) y qué patrones no se implementan pero se pueden incorporar fácilmente (azul).
Microservices.io contiene mucha información útil y bien escrita sobre los patrón / arquitectura de microservicio y las dificultades para implementarlos correctamente. Si es nuevo en esta arquitectura, puede ayudarlo a ponerse al día rápidamente y probablemente lo ayudará a utilizar Microdot al máximo.
Características
Un contenedor de servicios que acepta parámetros de línea de comandos que definen cómo se ejecuta el servicio, por ejemplo, como un proceso de línea de comandos o un servicio de Windows, con o sin registros de consola, el puerto que usará su servicio para escuchar las solicitudes entrantes, ya sea que se ejecute solo o como parte de un clúster (y el nombre del clúster al que unirse), y si debe cerrarse correctamente una vez que sale un PID principal supervisado. Los valores predeterminados sensibles se utilizan en función de su configuración de compilación (Release / Debug).
Comunicación RPC entre servicios que permite que los servicios se llamen entre sí. Cada servicio expone una o más interfaces C#, y los clientes lo llaman al recibir una instancia de una interfaz que realiza RPC transparente usando JSON sobre HTTP. Esto incluye balanceo de carga del lado del cliente (no es necesario un equilibrador de carga frente a su servicio), soporte de conmutación por error y comunicación segura a través de HTTPS con validaciones de certificados para servicios sensibles, si es necesario.
Almacenamiento en caché de respuestas transparentes , opt-in y del lado del cliente entre servicios. Útil para reducir la latencia de un extremo a otro cuando muchos de sus servicios dependen de unos pocos servicios centrales que brindan datos relativamente estáticos que, finalmente, pueden ser consistentes. También es útil para reducir el impacto de la falla de dichos servicios, mientras que los clientes aún almacenan en caché sus respuestas.
Instalaciones de registro y seguimiento distribuido para ayudar a diagnosticar problemas en producción, como el seguimiento de excepciones . Los eventos del lado del cliente y del servidor se emiten para cada llamada y se pueden usar para rastrear cómo se manejó una solicitud en todos los servicios (el árbol de llamadas) y la latencia que contribuyó cada uno.
Descubrimiento del servicio del lado del cliente que admite el descubrimiento basado en configuración manual o Consul de HashiCorp.
Todos los componentes emiten métricas de rendimiento a través de Metrics.NET para supervisar el rendimiento en tiempo real.
Se proporcionan comprobaciones de estado detalladas para cada subsistema y se pueden ampliar fácilmente para cubrir las dependencias externas de su servicio.
Un sistema de configuración jerárquica basado en archivos XML que permite invalidar valores en función de dónde y cómo se aloja el microservicio (por centro de datos, entorno y microservicio). La configuración se consume del código a través de objetos fuertemente tipados con mapeo automático y se actualiza en tiempo real cuando cambian los archivos XML.
Diseño altamente modular y soporte de inyección de dependencia de primera clase utilizando Ninject , lo que le permite intercambiar cada componente con su propia implementación si es necesario.
Herramientas para ayudar a probar su servicio, para pruebas unitarias, pruebas de componentes de servicio y prueba de contrato de integración de servicios.
Integración con Orleans
Microdot proporciona integración con Microsoft Orleans que, a su vez, proporciona:
- Facilidad de desarrollo: un modelo de programación simple ( actores virtuales ) que lo libera de lidiar con subprocesos, bloqueos, mutex, transacciones, consistencia de estado distribuido, etc.
- Escale verticalmente: escriba código asincrónico y utilice toda la potencia de su máquina; solo un hilo por núcleo de CPU, multitarea cooperativa y E/S asíncrona. El resultado son servicios de alto rendimiento, baja latencia y bajos gastos generales.
- Escala horizontal : sin ningún cambio en su código, puede escalar su servicio a cualquier número de nodos sin interrumpir el servicio.
- Resiliencia : la falla de un nodo solo afecta las operaciones en vuelo que ocurren en ese nodo, pero su servicio permanece operativo y el trabajo se redistribuye entre los nodos en buen estado. Orleans también maneja con gracia situaciones como fallas de múltiples nodos, cerebro dividido y otros desastres.
- Baja latencia y E/S de disco : al almacenar automáticamente en caché las entidades comerciales más activas, para que no sea necesario cargarlas desde el disco cuando sea necesario leer su estado.
Puede optar por implementar sus microservicios en Orleans o no (o solo algunos de ellos). En general, probablemente sea mejor usar Orleans, pero en ciertos casos es posible que desee no hacerlo, por ejemplo, si tiene un servicio sin estado que no requiere coherencia o coordinación interna, como una puerta de enlace API, un repositorio encima de un base de datos (que maneja la concurrencia), funciones puras como cálculos complejos, procesamiento o generación de imágenes o documentos, o un servicio proxy a sistemas externos.
El resto de este documento utiliza jerga orleana como granos (Grains) y silos.
Grains
Los Grains son las primitivas clave del modelo de programación de Orleans. Los granos son los componentes básicos de una aplicación Orleans, son unidades atómicas de aislamiento, distribución y persistencia. Los granos son objetos que representan entidades de aplicación (entities). Al igual que en la programación clásica orientada a objetos, un grano encapsula el estado de una entidad y codifica su comportamiento en la lógica del código. Los granos pueden tener referencias entre sí e interactuar invocando los métodos de los demás expuestos a través de interfaces. (parecidos a los beans en Java)
Otra nota interesante sobre los Grains es que Orleans los gestiona automáticamente. No tiene que preocuparse por crear instancias o administrarlos. Orleans los llama actores virtuales en oposición a actores tradicionales.
Silos
¿Dónde viven los Grains? en los Silos, por supuesto.
Los silos son los que albergan y ejecutan los Grains. Nuevamente, los granos son sus objetos que exponen el comportamiento y encapsulan el estado. Orleans crea los granos en el Silo y los ejecuta allí. Su código de cliente hará referencia solo a las interfaces que implementan sus granos.
Ah, y por supuesto, también puedes tener un grupo de silos.
Arquitectura de alto nivel
Arquitectura del sistema
Un servicio (verde) se compone de varios nodos, cada uno es un host Microdot (azul) que está ejecutando un Silo Orleans (violeta). El anfitrión acepta llamadas RPC a través de JSON sobre HTTP y las reenvía al Silo. Las llamadas al host pueden provenir de clientes (amarillo), por ejemplo, frontend o de otros servicios. Cada silo de Orleans es parte de un clúster de Orleans y cada silo se comunica con otros silos del clúster mediante un protocolo de comunicación binario propio. Cada Silo en un clúster de Orleans también se conecta a una Tabla de miembros (por ejemplo, ZooKeeper, Consul, Azure u otra base de datos de alta disponibilidad), que utiliza para descubrir otros Silos en el mismo clúster (no se muestra en el diagrama).
Arquitectura de Nodo
Cada nodo está compuesto por un host Microdot que contiene tres componentes principales: HttpServiceListener (azul oscuro), Service Grain (naranja) y otros granos (blanco).
- HttpServiceListener es responsable de escuchar las solicitudes HTTP entrantes, analizarlas y llamar al método apropiado en Service Grain.
- Service Grain es responsable de exponer y manejar la API pública de su servicio. Recibirá llamadas de HttpServiceListener y necesita hacer un procesamiento inicial en ellas y, por lo general, enviarlas a otros granos. Es requerido por el framework de Microdot y se trata como el punto de entrada de su servicio.
- Todos los demás granos son responsables de las funciones principales de su servicio. La mayoría, si no toda, la lógica de su servicio residirá en esos granos. Los métodos en estos granos no están expuestos a través de Microdot y solo se pueden llamar desde dentro de ese servicio (excepto cuando se usa una función de Orleans, ‘Outside Grain Client’, en cuyo caso es posible llamar a cualquier grano directamente usando el protocolo de comunicación binaria de Orlean , pero esto se puede bloquear si se desea).
- La interfaz de servicio, una interfaz .NET ordinaria que define la API de cara al público de su servicio, se publica a través de NuGet (generalmente un servidor interno) para que otro cliente pueda llamar a su servicio (por ejemplo, otros servicios, frontend / GUI, herramientas de DevOps, etc).
- El cliente utiliza la interfaz de servicio NuGet junto con ServiceProxy, que genera (en tiempo de ejecución) un cliente que implementa esa interfaz. Todas las llamadas al cliente se transforman en JSON que contiene el método que se llamó, los argumentos que se pasaron al método y datos de seguimiento adicionales. El JSON se envía al servicio a través de HTTP (el nombre de host, el puerto y el protocolo se resuelven mediante Service Discovery) y el servicio remoto devuelve un JSON que representa el valor de retorno del método, que se deserializa y se devuelve al llamador del ServiceProxy.
Fantástico!
Fuente: https://github.com/gigya/microdot
En la próxima entrega demostraré su funcionamiento con un ejemplo concreto. Orleans es funcional a aplicaciones que deseen escribirse en .NET estándar o en .NET Core.