2012-07-07 22 views
8

Tengo un número desconocido de trabajos para ser ejecutados por un número conocido (por supuesto) de actores. El número de trabajos iniciales puede aumentar después de que un actor complete un trabajo. Es decir, un actor, al completar su tarea, podría agregar un nuevo trabajo para ser ejecutado.Cómo saber si un actor está inactivo

La forma en que estoy manejando esto es hacer que cada actor envíe un mensaje al maestro cuando completa su trabajo, no solo con el resultado de la ejecución sino también con una 'bandera' que indica que el actor está ahora inactivo . El maestro tiene una cola de trabajos y una cola de actores ociosos, cada vez que un actor envía un 'mensaje de trabajo terminado', el maestro verificará si hay algo más para ese actor que hacer ... y así sucesivamente hasta la cola de trabajos está vacío y la cola inactiva está llena ... en ese punto apagué el sistema. No hay mucha supervisión aquí, así que siento que no lo estoy haciendo bien ...

No estoy usando un enrutador porque no pude encontrar una forma de consultar al enrutador para los actores inactivos, entonces mi pregunta es:

¿Cuál es la forma "correcta" de manejar la situación que he descrito anteriormente en Akka?

Respuesta

7

Deberías echar un vistazo a Akka's routing capabilites.SmallestMailboxRouter podría ser lo que estás buscando.

Como alternativa, puede crear actores a pedido, es decir, para cada tarea, se crea dinámicamente un nuevo actor. Un actor central realiza un seguimiento de todos los actores que están activos actualmente. Una vez que un actor trabajador termina, se envía a sí mismo un PoisonPill e informa al maestro sobre su cierre (activamente, o mediante el mensaje estándar Terminate que Akka enviará al actor supervisor). Una vez que no haya más actores activos, es decir, no más tareas, el actor controlador apagará el sistema.

adición después de leer el comentario: Tome un vistazo a las fuentes de SmallestMailboxLike, un rasgo Scala mezclado por SmallestMailboxRouter. Advertencia: debes tener un conocimiento básico de Scala. Pero esto es generalmente una buena idea de todos modos, si desea utilizar Akka ... isProcessingMessage(ActorRef) El método se puede entender como isNotIdle(ActorRef)

// Returns true if the actor is currently processing a message. 
// It will always return false for remote actors. 
// Method is exposed to subclasses to be able to implement custom 
// routers based on mailbox and actor internal state. 
protected def isProcessingMessage(a: ActorRef): Boolean = a match { 
    case x: LocalActorRef ? 
    val cell = x.underlying 
    cell.mailbox.isScheduled && cell.currentMessage != null 
    case _ ? false 
} 

// Returns true if the actor currently has any pending messages 
// in the mailbox, i.e. the mailbox is not empty. 
// It will always return false for remote actors. 
// Method is exposed to subclasses to be able to implement custom 
// routers based on mailbox and actor internal state. 
protected def hasMessages(a: ActorRef): Boolean = a match { 
    case x: LocalActorRef ? x.underlying.mailbox.hasMessages 
    case _    ? false 
} 
+0

Pasé por el enrutamiento de Akka y es por eso que decidí no usar un enrutador (quizás debería escribir el mío) porque no puedo consultar un enrutador sobre el estado inactivo de los trabajadores (tal vez estoy equivocado, ¿podría indicarme dónde? para mirar?) – DodoTheDeadDoo

+0

No quise presionar enter ...De todos modos, investigaré la solución de la píldora venenosa, es como lo que estoy haciendo en este momento, no mato a un trabajador, simplemente lo puse a ralentí para que pueda ser reutilizado ... cuando ya no tengo más tareas Y todos los trabajadores están inactivos de lo que sé que he terminado. – DodoTheDeadDoo

+0

Así que escribiré mi propio enrutador :) – DodoTheDeadDoo

1

Otra estrategia puede ser el uso de un BalancingDispatcher y una RoundRobinRouter (como un "pool", el actor) De Akka docs:

BalancingDispatcher 
# This is an executor based event driven dispatcher that will try to redistribute work from busy actors to idle actors. 




# All the actors share a single Mailbox that they get their messages from. 

It is assumed that all actors using the same instance of this dispatcher can process all messages that have been sent to one of the actors; i.e. the actors belong to a pool of actors, and to the client there is no guarantee about which actor instance actually processes a given message. 

# Sharability: Actors of the same type only 

# Mailboxes: Any, creates one for all Actors 

# Use cases: Work-sharing 

definir su despachador en application.conf o cargar mediante programación en el arranque.

private final static Config akkaConfig = ConfigFactory.parseString(

      "my-dispatcher.type = BalancingDispatcher \n" + 
      "my-dispatcher.executor = fork-join-executor \n" + 
      "my-dispatcher.fork-join-executor.parallelism-min = 8 \n" + 
      "my-dispatcher.fork-join-executor.parallelism-factor = 3.0 \n" + 
      "my-dispatcher.fork-join-executor.parallelism-max = 64 " 
); 

A continuación, defina el enrutador y el despachador de las rutas.

getContext().actorOf(new Props(MyActor.class).withRouter(new RoundRobinRouter(10)).withDispatcher("my-dispatcher"), "myActor"); 

Así que el router simplemente ir de mensajes "de distribución", y el despachador se ejecutará un agente seleccionado (y se pone en práctica el trabajo de robar también)

-1

Equilibrio despachador utilizará sólo un buzón para toda la actores creados que se crean todos con BalancingDispatcher. Por lo tanto, hará que su trabajo sea simple.

Cuestiones relacionadas