akka - películas - shahrukh khan y su esposa
¿Cuándo usar Actors vs Futures? (3)
Actualmente estoy trabajando en un juego! Proyecto que tiene la siguiente arquitectura:
Controladores -> Servicios (actores) -> Modelos (clases de casos regulares)
Para cada solicitud que ingrese, emitiremos una llamada a las capas de servicio así:
Service ? DoSomething(request, context)
Tenemos un número establecido de estos actores de servicio detrás de un enrutador akka que se crean durante la inicialización de la aplicación y se pueden expandir a pedido.
Y en el servicio, principalmente hacemos una modesta manipulación de datos o llamadas a bases de datos:
receive = {
case DoSomething(x, y) => {
...
Model.doSometing(...)
sender ! result
}
}
Tengo dudas sobre si deberíamos usar actores para nuestros servicios o solo usar Futures solamente.
No tenemos ningún estado interno que deba modificarse en los actores del servicio, cualquier mensaje que se envíe va a una función y escupe el resultado. ¿No es esta la gran fuerza del modelo de actor?
Estamos haciendo muchas tareas que parecen alejar mucho del modelo de actor
No estamos haciendo cálculos pesados y la comunicación remota no tiene sentido porque la mayor parte del trabajo es que la base de datos y el viaje de ida y vuelta a un actor remoto para hacer una llamada de db sea innecesaria
Usamos reactivemongo, por lo que cada llamada de db no está bloqueando. Podemos hacer muchas de estas llamadas.
Me parece que eliminar akka y solo usar Futures hace nuestra vida mucho más fácil y realmente no perdemos nada.
Ciertamente, no hay escasez de opiniones sobre el tema de lo que debería y no debería ser un actor. Al igual que estos dos mensajes:
http://noelwelsh.com/programming/2013/03/04/why-i-dont-like-akka-actors/
http://www.chrisstucchio.com/blog/2013/actors_vs_futures.html
No creo que vayas a encontrar una respuesta absoluta a esta pregunta, excepto que es situacional y realmente depende de tus preferencias y tu problema. Lo que puedo hacer por usted es ofrecer mi opinión que se basa en que nosotros implementemos Akka durante aproximadamente 2 años.
Para mí, me gusta pensar en Akka realmente como una plataforma. Venimos por el Modelo de actor, pero nos quedamos por todas las otras bondades que la plataforma proporciona como Clustering / Remoting, FSM, Routing, Circuit Breaker, Throttling y similares. Estamos tratando de construir una arquitectura similar a SOA con nuestros actores actuando como servicios. Estamos implementando estos servicios en un clúster, por lo que estamos aprovechando cosas como la transparencia de la ubicación y el enrutamiento para proporcionar a un consumidor de servicios (que a su vez podría ser otro servicio) encontrar y utilizar un servicio sin importar dónde esté implementado. y de una manera altamente disponible. Akka hace que todo este proceso sea bastante simple basado en las herramientas de plataforma que ofrecen.
Dentro de nuestro sistema, tenemos el concepto de lo que yo llamo Servicios de Fundación. Estos son servicios realmente simples (como servicios básicos de búsqueda / administración para una entidad en particular). Estos servicios generalmente no llaman a ningún otro servicio y, en algunos casos, solo realizan búsquedas de base de datos. Estos servicios están agrupados (enrutador) y generalmente no tienen ningún estado. Son muy similares a lo que estás describiendo como algunos de tus servicios. Entonces comenzamos a construir servicios cada vez más complejos sobre estos servicios básicos. La mayoría de estos servicios son de corta duración (para evitar preguntar), a veces basados en FSM, que recopilan datos de los servicios básicos y luego los contrarrestan y hacen algo como resultado. A pesar de que estos servicios básicos son bastante simples, y algunos dirían que no requieren un actor, me gusta la flexibilidad en que cuando los compongo en un servicio de nivel superior, puedo buscarlos y pueden estar en cualquier lugar (ubicación transparente) ) en mi grupo con cualquier número de instancias disponibles (enrutamiento) para usar.
Entonces, para nosotros, fue realmente una decisión de diseño basar a un actor como una especie de servicio similar a un micro que está disponible dentro de nuestro clúster para ser consumido por cualquier otro servicio, sin importar qué tan simple sea ese servicio. Me gusta comunicarme con estos servicios, donde sea que estén, a través de una interfaz de grano grueso de manera asíncrona. Muchos de esos principios son aspectos de la construcción de una buena SOA. Si ese es tu objetivo, entonces creo que Akka puede ser muy útil para lograr ese objetivo. Si no está buscando hacer algo así, entonces tal vez tenga razón al cuestionar su decisión de usar Akka para sus servicios. Como dije antes, depende realmente de usted averiguar qué está tratando de hacer desde una perspectiva de arquitectura y luego diseñar su capa de servicios para cumplir esos objetivos.
Creo que estás en el camino correcto.
No tenemos ningún estado interno que deba modificarse en los actores del servicio, cualquier mensaje que se envíe va a una función y escupe el resultado. ¿No es esta la gran fuerza del modelo de actor?
Encontré el blog de Chris Stucchio (referido por @cmbaxter arriba) al instante encantador. Mi caso era tan simple que las consideraciones arquitectónicas no eran un punto válido. Solo enrutamiento de rociado y mucho acceso a la base de datos, como usted tiene. Ningún estado Así el futuro. Código mucho más simple.
Me preguntaba lo mismo y lo que decidimos hacer fue usar Akka para el acceso a nuestros datos y funciona muy bien, es muy comprobable (y probado) y muy portátil.
Creamos repositorios, actores de larga vida, que iniciamos en nuestra aplicación: (Para su información, estamos usando Slick para nuestro acceso a DB, pero también tenemos un diseño similar para nuestras necesidades de MongoDB)
val subscriptionRepo = context.actorOf(Props(new SubscriptionRepository(appConfig.db)), "repository-subscription")
Ahora podemos enviar un mensaje de "Solicitud" para datos, por ejemplo:
clase de caso SubscriptionsRequested (atDate: ZeroMillisDateTime)
que el actor responderá con
case class SubscriptionsFound(users: Seq[UserSubscription])
o Fracaso (excepción)
En nuestra situación (aplicaciones de aplicación, pero también CLI), envolvimos esas llamadas en un actor de vida corta que toma el contexto y lo completa en la recepción y se cierra a sí mismo. (Puede manejar la lógica específica del dominio en esos actores, tenerlo para extender a otro actor que gestione su ciclo de vida y excepción, de modo que solo tendría que especificar una función parcial para sus necesidades y dejar que el actor abstracto se ocupe de los tiempos de espera, las excepciones comunes, etc.
También tenemos situaciones en las que necesitábamos más trabajo en el actor iniciador, y es muy conveniente disparar x mensajes a tus repositorios y hacer que tu actor almacene esos mensajes a medida que llegan, haciendo algo una vez que están allí, disparando para Completar al remitente (por ejemplo) y cerrarse.
Gracias a este diseño, tenemos un repositorio muy reactivo que vive fuera de nuestra aplicación, completamente probado con Akka TestKit y H2, completamente independiente de DB, y es muy fácil acceder a los datos de nuestros DBs (y nunca hacemos ASK, solo Tell: Indicar a repo, decirle al remitente, completar o x Contar a reposiciones, hacer coincidir el patrón de los resultados esperados hasta completar, indicar al remitente).