Pregunta

Debido a que mi primera pregunta fue tan larga, lo que te pido esto como una cuestión aparte. Es otro sobre la arquitectura de una aplicación basada en el actor.

Hacer un seguimiento de rutas de mensajes a través de una aplicación

Vamos a tomar una pieza de código Java:

public void deleteTrades(User user, Date date) {
    PermissionSet ps = permissionService.findPermissions(user)
    if (ps.hasPermission("delete")) {
        Set<Trade> ts = peristence.findTrades(date);
        reportService.sendCancelReports(ts);
        positionService.updateWithDeletedTrades(ts);
    }
}

En este código tengo 4 componentes separados y la interacción entre ellos requerida para la deleteTrades procedimiento está bien definido. Está completamente contenida en el deleteTrades método.

Modelado esto con Actors y reemplazar mis 4 componentes con 4 actores separados, cómo puedo realizar un seguimiento (en mi mente) de lo que un procedimiento consiste? Sobre todo si estoy evitando el uso de la !? operador, entonces lo más probable es que voy a enviar un mensaje a mi ConditionalDelete PermissionActor, que se vayan a enviar un mensaje a mi GetTradesAndDelete PersistenceActor que luego enviar más mensajes etc, etc. El código para procesar una eliminación será esparcida a través de mi aplicación.

También significa que prácticamente cada actor necesita una manija en cada otro actor (en orden para enviar mensajes).

Al igual que en mi anterior pregunta, ¿cómo las personas a lidiar con esto? ¿Hay una buena herramienta de modelado que le permite realizar un seguimiento de todo esto? Qué la gente usa !? ¿Estoy girando demasiados componentes en Actors?

¿Fue útil?

Solución

Se utiliza 5 componentes, sin duda. Hay agentes que se ocupan de tareas específicas, y hay un orquestador también.

La pregunta que debe tener, por supuesto, es cómo se puede encadenar este assynchronously. Bueno, en realidad es algo fácil, pero puede oscurecer el código. Básicamente, se envía cada componenent la respuesta que desea.

react {
  case DeleteTrades(user,dates) => 
    PermissionService ! FindPermissions(user, DeleteTradesPermissions(dates) _)
  case DeleteTradesPermissions(dates)(ps) =>
    if (ps hasPermission "delete")
      Persistence ! FindTrades(date, DeleteTradesTradeSet _)
  case DeleteTradesTradeSet(ts) =>
    ReportService ! SendCancelReports(ts)
    PositionService ! UpdateWithDeletedTrades(ts)
}

Aquí se utiliza para pasar currying "fechas" en la primera respuesta de regresar. Si hay una gran cantidad de parámetros asociados con una interacción, que podría ser mejor para mantener la información de todas las transacciones en curso en un HashSet local y sólo tiene que pasar una señal de que vamos a usar para localizar esa información cuando se recibe la respuesta.

Tenga en cuenta que esto solo actor puede manejar múltiples acciones simultáneas. En este caso particular, basta con borrar las transacciones, pero se puede agregar cualquier número de diferentes acciones para que su manipulación. Cuando los datos necesarios para una acción está listo, entonces esa acción continúa.

Editar

Este es un ejemplo práctico de cómo se pueden definir estas clases:

class Date
class User
class PermissionSet

abstract class Message
case class DeleteTradesPermission(date: Date)(ps: PermissionSet) extends Message
case class FindPermissions(u: User, r: (PermissionSet) => Message) extends Message

FindPermissions(new User, DeleteTradesPermission(new Date) _)

Algunas explicaciones sobre currying y funciones. La clase se DeleteTradesPermission curry para que pueda pasar una Date en él, y tener alguna otra función completarlo con un PermissionSet. Este sería el patrón de los mensajes de respuesta.

Ahora, el FindPermissions clase recibe como un segundo parámetro de una función. El actor que recibe este mensaje pasará el valor de retorno de esta función, y recibirá un Message para ser enviados como respuesta. En este ejemplo, el mensaje tendrá tanto el Date, que el actor llamado envió, y PermissionSet, que el contestador actor está proporcionando.

Si no se espera respuesta, como es el caso de DeleteTrades, SendCancelReports y UpdateWithDeletedTrades para los fines de este ejemplo, entonces no es necesario pasar una función del mensaje de retorno.

Desde que estamos esperando una función que devuelve un mensaje como parámetro para aquellos mensajes que requiere una respuesta, podríamos definir los rasgos de la siguiente manera:

trait MessageResponse1[-T1] extends Function1[T1, Message]
trait MessageResponse2[-T1, -T2] extends Function2[T1, T2, Message]
...

Otros consejos

Los actores no deben ser utilizados para reemplazar los componentes de servicios tradicionales sin consideraciones.

La mayor parte de los componentes de servicio que escribimos hoy en día, por la formación, son apátridas. componentes de servicio sin estado son más fáciles de manejar (clase de mensaje sin, etc) que los actores. Una de las cosas que les faltan, sin embargo, cuando se compara con los actores, es la ejecución asíncrona. Pero cuando los clientes están esperando los resultados de regresar de forma sincrónica mayor parte del tiempo, los componentes de servicio sin estado síncronas están bien para el trabajo.

Actor es una buena opción cuando hay estados internos para manejar. No hay necesidad de hacer ninguna sincronización dentro "acto ()" para acceder a los estados internos y de preocuparse por las condiciones de carrera. Mientras "!?" no se utiliza dentro "acto ()", supercondenación debe minimizarse también.

Los actores deben tener cuidado de cualquier procesamiento de bloqueo realizado durante la manipulación de los mensajes. Desde actores procesan su mensajes secuencialmente, en cualquier momento que se bloquean a la espera de I / O en el interior de "acto ()", que no puede procesar los otros mensajes en sus buzones. El lenguaje Scala a utilizar aquí es comenzar otro actor ad-hoc que hace la operación real de bloqueo. Esta anti-patrón afecta (reaccionar) agente basado en eventos aún más debido a que bloquea el hilo el actor basado en eventos es piggy-backed en también.

A partir de lo que he entendido, los cuatro de sus llamadas a los componentes de servicio son potencialmente bloqueando, por lo que se deben tomar cuidados para hacerlos escala al convertir a los actores.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top