2017-03-27 2 views
1

Ich versuche, den folgenden Anwendungsfall als Teil meiner akka zu implementierenGraceful Beendigung

Lernen würde Ich mag die Gesamt Straßen in allen Städten aller Staaten berechnen. Ich habe eine Datenbank, die die benötigten Details enthält. Hier ist, was ich bisher

Konfiguration

akka.actor.deployment { 
/CityActor{ 
    router = random-pool 
    nr-of-instances = 10 
} 
/StateActor { 
    router = random-pool 
    nr-of-instances = 1 
}} 

Haupt

public static void main(String[] args) { 

    try { 

     Config conf = ConfigFactory 
       .parseReader(
         new FileReader(ClassLoader.getSystemResource("config/forum.conf").getFile())) 
       .withFallback(ConfigFactory.load()); 

     System.out.println(conf); 

     final ActorSystem system = ActorSystem.create("AkkaApp", conf); 

     final ActorRef masterActor = system.actorOf(Props.create(MasterActor.class), "Migrate"); 

     masterActor.tell("", ActorRef.noSender()); 

    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
} 

MasterActor

public class MasterActor extends UntypedActor { 

private final ActorRef randomRouter = getContext().system() 
     .actorOf(Props.create(StateActor.class).withRouter(new akka.routing.FromConfig()), "StateActor"); 

@Override 
public void onReceive(Object message) throws Exception { 

    if (message instanceof String) { 

     getContext().watch(randomRouter); 

     for (String aState : getStates()) { 
      randomRouter.tell(aState, getSelf()); 
     } 
     randomRouter.tell(new Broadcast(PoisonPill.getInstance()), getSelf()); 

    } else if (message instanceof Terminated) { 

     Terminated ater = (Terminated) message; 

     if (ater.getActor().equals(randomRouter)) { 
      getContext().system().terminate(); 
     } 
    } 
} 

public List<String> getStates() { 
    return new ArrayList<String>(Arrays.asList("CA", "MA", "TA", "NJ", "NY")); 
};} 

StateActor

public class StateActor extends UntypedActor { 

private final ActorRef randomRouter = getContext().system() 
     .actorOf(Props.create(CityActor.class).withRouter(new akka.routing.FromConfig()), "CityActor"); 

@Override 
public void onReceive(Object message) throws Exception { 
    if (message instanceof String) { 
     System.out.println("Processing state " + message); 

     for (String aCity : getCitiesForState((String) message)) { 
      randomRouter.tell(aCity, getSelf()); 
     } 
     Thread.sleep(1000); 
    } 
} 

public List<String> getCitiesForState(String stateName) { 
    return new ArrayList<String>(Arrays.asList("Springfield-" + stateName, "Salem-" + stateName, 
      "Franklin-" + stateName, "Clinton-" + stateName, "Georgetown-" + stateName)); 
};} 

CityActor

public class CityActor extends UntypedActor { 

@Override 
public void onReceive(Object message) throws Exception { 
    if (message instanceof String) { 
     System.out.println("Processing city " + message); 
     Thread.sleep(1000); 
    } 
}} 

i richtig diesen Anwendungsfall implementieren Hat?

Ich kann den Code nicht richtig beenden, ich bekomme tote Briefe Nachrichten. Ich weiß, warum ich sie bekomme, aber nicht sicher, wie ich es richtig umsetzen soll.

Jede Hilfe wird sehr geschätzt. Danke

Antwort

0

Ich testete und lief Ihren Anwendungsfall mit Akka 2.4.17. Es funktioniert und endet ordnungsgemäß, ohne dass irgendwelche toten Briefe protokolliert werden.

Hier sind einige Bemerkungen/Anregungen Ihr Verständnis des Akka Toolkit zu verbessern:

  1. nicht Thread.sleep() innerhalb Schauspieler anwenden. Grundsätzlich ist es nie eine gute Übung, da ein Thread für viele Akteure viele Aufgaben übernehmen kann (dies ist das Standardverhalten mit einem gemeinsamen Thread-Pool). Stattdessen können Sie einen Akka-Scheduler verwenden oder einem bestimmten Actor einen einzelnen Thread zuweisen (weitere Informationen finden Sie unter this post). Siehe auch die Akka documentation zu diesem Thema.

  2. Einige tote Buchstaben sind nicht immer ein Problem. Es tritt im Allgemeinen auf, wenn das System einen Actor stoppt, der einige Nachrichten in seinem Postfach hatte. In diesem Fall werden die verbleibenden unverarbeiteten Nachrichten an deadLetters der ActorSystem gesendet. Ich empfehle Ihnen, die Konfiguration zu überprüfen, die Sie für die Protokollierung von toten Briefen bereitgestellt haben. Wenn die von Ihnen bereitgestellte Datei forum.conf Ihre vollständige Konfigurationsdatei für Akka ist, können Sie einige zusätzliche Einstellungen anpassen. Siehe Seite Logging of Dead Letters und Stopping actors auf Akkas Website. Zum Beispiel könnten Sie einen Abschnitt wie diese:

    akka { 
        # instead of System.out.println(conf); 
        log-config-on-start = on 
    
        # Max number of dead letters to log 
        log-dead-letters = 10 
    
        log-dead-letters-during-shutdown = on 
    } 
    
  3. Statt System.out.println() der Verwendung von/debug zu protokollieren, ist es bequemer, einen dedizierten Logger für jeden Schauspieler einrichten, die Ihnen zusätzliche Informationen wie Disponenten bietet, Schauspieler Name, etc. Wenn Sie interessiert sind, schauen Sie auf die Logging Seite.

  4. Verwenden Sie einige benutzerdefinierte immutable message objects anstelle von systematischen Strings. Zunächst mag es schmerzhaft erscheinen, neue zusätzliche Klassen deklarieren zu müssen, aber am Ende hilft es, komplexe Verhaltensweisen besser zu entwerfen und es ist lesbarer. Zum Beispiel kann ein Schauspieler A auf eine RequestMsg antworten, die von einem Schauspieler B mit einer AnswerMsg oder einer benutzerdefinierten ErrorMsg kommt. Dann für Ihre Schauspieler B, werden Sie mit der folgenden onReceive() Methode am Ende:

    @Override 
    public void onReceive(Object message) { 
        if (message instanceof AnswerMsg) { 
         // OK 
         AnswerMsg answerMsg = (AnswerMsg) message; 
         // ... 
        } 
        if (message instanceof ErrorMsg) { 
         // Not OK 
         ErrorMsg errorMsg = (ErrorMsg) message; 
         // ... 
        } 
        else { 
         // Unexpected behaviour, log it 
         log.error("Error, received " + message.toString() + " object.") 
        } 
    } 
    

Ich hoffe, dass diese Mittel für Sie von Nutzen sein werden.

Haben Sie eine glückliche Akka Programmierung! ;)