优雅的终止

时间:2017-03-27 03:37:24

标签: akka

我正在尝试将以下用例作为我的akka​​学习的一部分来实现

我想计算所有州所有城市的街道总数。我有一个包含所需细节的数据库。这是我到目前为止所拥有的

配置

import UIKit

class ThirdViewController: UIViewController {

    var orderTextController = SecondViewController().orderType

    override func viewDidLoad() {
        super.viewDidLoad()
        order1Label.text = orderTextController
    }

    override func viewWillAppear(animated: Bool) {
        order1Label.text = orderTextController
    }

    @IBOutlet var order1Label: UILabel!

}

主要

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

MasterActor

    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();
    }
}

StateActor

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

CityActor

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

我是否正确实施了这个用例?

我无法正确终止代码,我收到了死信。我知道为什么我会得到它们,但不知道如何正确实现它。

非常感谢任何帮助。 感谢

1 个答案:

答案 0 :(得分:0)

我使用Akka 2.4.17测试并运行了您的用例。它正常工作和终止,没有记录任何死信。

以下是一些有助于提高您对Akka工具包的理解的评论/建议:

  1. 不要在演员中使用Thread.sleep()。基本上,它永远不是一个好的做法,因为同一个线程可以为许多actor执行许多任务(这是共享线程池的默认行为)。相反,您可以使用Akka调度程序或将单个线程分配给特定的Actor(有关详细信息,请参阅this post)。另请参阅有关该主题的Akka documentation

  2. 有一些死信并不总是一个问题。通常在系统停止其邮箱中包含某些邮件的Actor时出现。在这种情况下,剩余的未处理消息将发送到deadLetters的{​​{1}}。我建议您检查您提供的用于记录死信的配置。如果您提供的文件ActorSystem是Akka的完整配置文件,您可能需要自定义一些其他设置。请参阅Akka网站上的页面Logging of Dead LettersStopping actors。例如,你可以有一个这样的部分:

    forum.conf
  3. 不是使用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 } 进行日志/调试,而是为每个Actor设置专用记录器更方便,它为您提供调度程序,演员姓名等附加信息。如果您有兴趣,请查看Logging页面。

  4. 使用一些自定义immutable message objects而不是系统字符串。首先,必须声明新的附加类似乎很痛苦,但最终它有助于更​​好地设计复杂的行为,并且它更具可读性。例如,演员A可以使用System.out.println()或自定义RequestMsg来回答来自演员B的AnswerMsg。然后,对于你的演员B,你将得到以下ErrorMsg方法:

    onReceive()
  5. 我希望这些资源对您有用。

    快乐的Akka节目! ;)