2012-07-07 11 views
8

Mam nieznaną liczbę zadań do wykonania przez znaną (oczywiście) liczbę aktorów. Początkowa liczba zadań może wzrosnąć po tym, jak aktor zakończy pracę. Oznacza to, że po zakończeniu zadania aktor może dodać nowe zadanie do wykonania.Jak sprawdzić, czy aktor jest bezczynny?

Sposób, w jaki to robię, polega na tym, aby każdy aktor wysłał komunikat do kapitana, gdy zakończy swoją pracę, nie tylko z wynikiem wykonania, ale także z "flagą" wskazującą, że aktor jest teraz bezczynny . Mistrz ma kolejkę zadań i kolejkę bezczynnych aktorów, ilekroć aktor przesyła komunikat "ukończone zadanie", mistrz sprawdzi, czy jest coś jeszcze do zrobienia ... tak dalej i tak dalej, aż do kolejki zadań jest pusty i kolejka jałowych jest pełna ... w tym momencie zamykam system. Tu nie ma większego nadzoru, więc czuję, że nie robię tego właściwie ...

Nie używam routera, ponieważ nie mogłem znaleźć sposobu na zapytanie o router dla bezczynnych aktorów, więc moje pytanie brzmi:

Jaki jest "właściwy" sposób postępowania z sytuacją opisaną powyżej w Akce?

Odpowiedz

7

Powinieneś rzucić okiem na Akka's routing capabilites.SmallestMailboxRouter może być tym, czego szukasz.

Alternatywnie można po prostu tworzyć aktorów na żądanie, tj. Dla każdego zadania nowy aktor jest tworzony dynamicznie. Główny aktor śledzi wszystkich aktorów, którzy są obecnie aktywni. Po zakończeniu działania robotnik wysyła do siebie numer PoisonPill i informuje go o jego zamknięciu (aktywnie lub za pośrednictwem standardowego komunikatu, który Akka prześle do nadzorującego aktora). Gdy nie ma już aktywnych aktorów, tj. Nie ma więcej zadań, aktor kontrolera wyłącza system.

Dodanie po przeczytaniu komentarza: Spójrz na źródłach SmallestMailboxLike, cecha Scala miesza się przez SmallestMailboxRouter. Ostrzeżenie: powinieneś mieć podstawową wiedzę o Scali. Ale to generalnie dobry pomysł, w każdym razie, jeśli chcesz używać Akka ... Metoda isProcessingMessage(ActorRef) można rozumieć jako 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

Przeszedłem przez routing Akki i dlatego zdecydowałem się nie używać routera (może powinienem napisać własny), ponieważ nie mogę zapytać routera o stan bezczynności pracowników (może jestem w błędzie, czy mógłbyś wskazać mi gdzie na które patrzysz?) – DodoTheDeadDoo

+0

Nie znaczy nacisnąć ...W każdym razie, zagłębię się w rozwiązanie z trucizną pigułką, to jest jak to, co teraz robię, nie zabijam pracownika, którego właśnie ustawiłem, żeby był bezczynny, aby mógł być ponownie wykorzystany ... kiedy nie mam więcej zadań I wszyscy pracownicy są bezczynni, niż wiem, że jestem skończony. – DodoTheDeadDoo

+0

Więc napiszę własny router :) – DodoTheDeadDoo

1

Inną strategią może być użycie BalancingDispatcher i RoundRobinRouter (jako „puli” aktor). Od 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 

Zdefiniuj dyspozytora w application.conf lub załadować go programowo na starcie.

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 " 
); 

Następnie określ router i dyspozytora dla tras.

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

Więc router po prostu pójść na wiadomości „Dystrybucja”, a dyspozytor będzie uruchomienie wybranego aktora (i realizuje prace kradzież również)

-1

dyspozytora Równoważenie będzie wykorzystywać tylko jedną skrzynkę dla wszystkich stworzonych aktorów, które są tworzone za pomocą BalancingDispatcher. Więc sprawi, że twoja praca będzie prosta.

Powiązane problemy