Código del ejemplo (GitHub)
AKKA es un toolkit que utiliza el modelo actor para proporcionar una plataforma en la que construir aplicaciones concurrentes y escalables. Adopta el modelo “let it crash” para la tolerancia a fallos, que se usa con gran éxito para construir aplicaciones capaces de “auto repararse” en sistemas que nunca se detienen.
Los actores son objetos que encapsulan estados y funciones y que se comunican exclusivamente a través de mensajes.
Las tareas asignadas a un actor pueden ser descompuestas en tareas más pequeñas que se asignen a otros actores. Para ello, creará nuevos actores hijo a los cuales asignará subtareas y supervisará. Cada actor en un sistema tiene un único padre, el cual es el actor que le ha creado. Todos los actores de un sistema son susceptibles de crear hijos a los que pasarán a supervisar automáticamente.
Cuando el actor termina su tarea, notifica al padre que esta está terminada. Si ocurre un error, también el padre es notificado del mismo. En este caso, el padre tiene distintas opciones, entre las que está reiniciar o parar el actor hijo o escalar el fallo. Todo depende del comportamiento deseado.
Toda la vida del actor ocurre dentro de un sistema de actores. Este sistema proporciona el entorno necesario para crear y ejecutar actores, así como para mantener una referencia a ellos. También es responsable de la creación del primer actor, /user: “the guardian actor”, que será el padre de nuestros actores. Aunque este es nuestro “punto de entrada” al sistema de actores, existen otros actores que el sistema crea.
Como he mencionado, toda comunicación con un actor se realiza a través de mensajes. Estos se comparan con la actual definición de funciones que tiene el actor para buscar la que se corresponda con el mensaje y será esa la ejecutada.
El actor dispone de una cola donde llegan los mensajes (Mailbox) y este nos asegura que los mensajes serán ejecutados por el actor en el mismo orden en que fueron encolados. Esta cola permite que no exista una dependencia entre actores, ya que la comunicación es totalmente asíncrona.
Uno de los mayores retos a la hora de usar AKKA es la definición de la arquitectura de actores que se usará. Normalmente, a la hora de definir la funcionalidad de un sistema, se haría a través de la definición de una serie de métodos en una interfaz para después completarlos mediante su implementación.
Cuando usamos actores, no podemos definir una API al uso y, para definir el comportamiento de nuestra aplicación, deberemos usar una serie de “protocolos” en lugar de interfaces. Estos protocolos están compuestos por los mensajes que un actor está capacitado para procesar y por los que el actor emitirá.
Normalmente, los mensajes se agrupan por categorías o patrones. Resulta más fácil así elegir entre ellos. Estos mensajes se suelen definir como clases internas estáticas y finales con acceso público (public static final class), así es más fácil reconocer el protocolo de cada actor de un sistema.
Los mensajes enviados entre actores en AKKA utilizan una característica de envío conocida por at-most-once-delivery (al menos se envía una vez). Esta característica asegura que todos los mensajes serán enviados 0 o 1 vez exactamente. Esto es, los mensajes pueden perderse, pero nunca duplicarse.
Esta característica permite una fácil implementación y un alto rendimiento frente a otras como at-least-once-delivery o exactly-once-delivery.
Tiene una menor sobrecarga de implementación porque puede usarse el conocido como fire-and-forget sin necesidad de mantener el estado del receptor o en el mecanismo de transporte.
Como conclusión, indicar que este tipo implementaciones puede ser interesante en entornos donde la escalabilidad y la disponibilidad de los sistemas (resilencia) son puntos muy importantes, pero llevarlos a entornos donde esas premisas no sean críticas puede ocasionar más problemas que soluciones aporta. En este enlace podéis encontrar el código fuente de una pequeña POC que se ha realizado para acompañar a este post.
Es una simple aplicación que registra una serie de valores bursátiles y permite su consulta. El sistema no entra a exponer cómo recuperar los valores bursátiles, simplemente estos (un pequeño conjunto de ellos) son cargados en el arranque del sistema. También expone, como parte de su protocolo, los mensajes necesarios para el registro de un nuevo valor o la actualización de uno ya existente.
Otra de las funciones expuestas por su protocolo es, claro está, la consulta de la cotización de un determinado valor. Para ello, tiene definidos dos mensajes, el de consulta y su respuesta.
Todo ello está integrado en una aplicación construida con Springboot y expuesto a través de unos simples métodos REST. Aunque este “envoltorio” puede ocasionar algo de ruido a la hora de exponer un simple ejemplo con AKKA, lo hemos creído más oportuno que mostrarlo a través de una clase main.