Posted: 09 Jun. 2021 7 Tiempo de lectura

Sistemas reactivos: El modelo actor en .NET

Introducción

Concurrencia, escalabilidad, resiliencia… Son algunos de los términos cada vez más comunes con los que nos encontramos los desarrolladores de .NET en nuestro día a día.

Lejos quedan los días en los que las aplicaciones de escritorio dominaban el mercado del desarrollo de software. El mercado ha ido generando (y sigue haciéndolo) una tendencia en la que los desarrollos de software forman parte de un ecosistema de servicios que interactúan entre sí a través de internet. El paso de los años nos ha demostrado que no existen las soluciones universales, y es por esto que han surgido multitud de arquitecturas y metodologías evolucionadas de sus predecesoras y adaptadas a las nuevas necesidades del mercado.

Cada vez es más común que nos encontremos con aplicaciones que necesitan reutilizar componentes y escalar dinámicamente, en base a la demanda que la aplicación necesita. Estos requerimientos nos hacen buscar soluciones que cubran este tipo de problemas, y aquí es donde destaca el modelo actor.

¿Qué es el modelo Actor?

El modelo actor nace en los años 70 de la mano de Carl Hewitt y Alan Kay para intentar dar solución a los problemas de lentitud y de consumo de memoria de sus programas, ya que los sistemas que existían por aquel entonces no podían mantener el nivel de rendimiento que necesitaban sus programas.

Según Wikipedia, el modelo actor se define de la siguiente manera: “en las ciencias de la computación es un modelo matemático de computación concurrente que toma al actor como la unidad primitiva universal de computación concurrente. En respuesta a un mensaje recibido, un actor puede: tomar decisiones locales, enviar más mensajes y determinar cómo responder al mensaje recibido”.

Básicamente, a un actor se le envían instrucciones a través de un mensaje y este devuelve información después de haber procesado dicho mensaje.

En el modelo actor, todo se basa en los mensajes, cada actor dispone de una dirección y cada mensaje es inmutable. Los mensajes se procesan uno a la vez y se gestionan por orden de llegada. En el modelo actor todo es asíncrono, y los actores no necesitan esperar a una respuesta de otro actor.

El modelo actor en .NET

Si bien existen más implementaciones del modelo actor en .NET, en este artículo hablaremos sobre Microsoft Orleans y su implementación.

Qué es Microsoft Orleans

Microsoft Orleans es un framework de código abierto y multiplataforma que nos permite construir aplicaciones robustas, escalables y distribuidas sin que tengamos que preocuparnos en aplicar tareas demasiado complejas para llevar a cabo nuestros propósitos.

Ha sido creado por Microsoft Research y nos introduce un nuevo concepto llamado Virtual Actor Model, el cual no es más que una abstracción del concepto de Actor y que nos ayuda a coger términos tan familiares como pueden ser objetos, interfaces, async/await, try/catch, etc. y extenderlos a entornos multi-servidor.

Granos

Los granos (actores virtuales) son la unidad fundamental de desarrollo en cualquier aplicación de Orleans. Se componen de una identidad, comportamiento y estado. Contienen, por tanto, la lógica de nuestra aplicación. Cada grano se ejecuta de forma asíncrona en un único hilo y están diseñados para ejecutar operaciones simples y rápidas.

Los granos pueden ser invocados por otros granos o por clientes externos como pueden ser Web frontends, a través de interfaces de comunicación fuertemente tipadas (contratos). Los granos se comunican con otros granos a través del envío de mensajes, los cuales se procesan secuencialmente por orden de llegada.

De la instanciación de los granos se encarga el runtime de Orleans, y se realiza de forma automática bajo demanda. Los granos que no se utilizan pasado un tiempo, se eliminan de la memoria para liberar recursos.

Silos

Los granos se ejecutan en silos, los cuales son el componente principal del runtime de Orleans.

Normalmente los silos se agrupan formando clústeres para escalabilidad y tolerancia a fallos, y cuando se ejecutan en este modo, se coordinan entre sí automáticamente para distribuirse la carga de trabajo, detectar fallos y recuperarse de los mismos.

Los clientes externos antes mencionados, realizan llamadas a los granos dentro del clúster a través de una librería cliente que gestiona la comunicación con los granos de forma automática.

Orleans, el modelo actor y los Microservicios

¿Es Orleans un framework para la construcción de microservicios?

Si bien esta es una discusión que sigue abierta hoy en día, y sobre la cual hay distintos puntos de vista, podríamos decir que Orleans es un framework que nos puede ayudar a la implementación de microservicios, pero que no conforma un framework de implementación de microservicios por sí mismo, es decir, Orleans nos ayuda en el desarrollo del sistema encargándose de la facilidad del desarrollo, escalabilidad, resiliencia y la baja latencia.

Se podría decir entonces que cada grano es un nano-servicio y que, combinando varios granos entre sí, se formaría un microservicio. Como ejemplo claro de esto tenemos Microdot.

Microdot es un framework nacido para la construcción de microservicios en .NET que se apoya mucho en Orleans, y como tal, conforma un framework completo que implementa y soporta muchos patrones de microservicios, permitiendo al desarrollador centrarse en la lógica del servicio sin la necesidad de tener que lidiar con toda la problemática de construir un sistema distribuido. Las características que nos ofrece Microdot por encima de Orleans son: contenedor de servicios, trazabilidad distribuida, descubrimiento de servicios en lado cliente, métricas de rendimiento, Service Component tests y Service integration contract tests.

Conclusión

La implementación del modelo actor supone un enfoque distinto al de la programación orientada a objetos, y si bien puede resultar extraño al principio, aplicado correctamente puede evitar muchos problemas inherentes a los sistemas distribuidos en el futuro.

De todos modos, y aunque en este artículo se han especificado las bondades de Orleans y de todo lo que aporta, deberemos analizar si realmente es justificable la introducción de un nivel de capas y complejidad tan elevado como este en nuestras aplicaciones.

 

Autor del artículo

Roberto Vázquez Iglesias, senior specialist de Consultoría Tecnológica de Deloitte