Akka-2.5.12学习系列(生命周期)

版权声明:转载请注明出处 https://blog.csdn.net/qiaojialin/article/details/80279516

本文用到的MyWork的源代码:Akka-2.5.12学习系列(第一个Actor)

生命周期

这里写图片描述

本文主要围绕这张图介绍生命周期

Actor 交给开发者的是一个引用,这个引用包括 path和UID,即可定位一个 Actor。

  • preStart() is invoked after the actor has started but before it processes its first message.

    preStart() 在 actor 启动后,处理第一条消息之前被调用。

  • postStop() is invoked just before the actor stops. No messages are processed after this point.

    postStop() 在 actor 停止之前调用,调用后不再接收消息。

  • preRestart() 在重启 Actor 之前在旧实例上调用

  • postRestart() 在重启 Actor 之后在新实例上调用,Actor.scala默认的postRestart()方法调用了preStart()方法

示例代码

为了控制 Actor 的 restart 和 resume,需要重写 supervisorStrategy() 方法,子 actor 抛出的异常都会被父 actor 接收,对于不同异常可以定义不同的处理方式。这里对 NullPointerException 进行 restart,对 IllegalArgumentException 进行 resume。

import akka.actor.*;
import akka.event.Logging;
import akka.event.LoggingAdapter;
import akka.japi.pf.DeciderBuilder;
import cn.edu.tsinghua.akka.MyWork;
import com.typesafe.config.ConfigFactory;
import scala.concurrent.duration.Duration;

import java.util.concurrent.TimeUnit;


/**
 * SuperVisor actor生成RestartActor,并接收RestartActor抛出的异常,并对RestartActor进行处理
 */
public class OverrideHandler extends UntypedAbstractActor{

    private LoggingAdapter log = Logging.getLogger(getContext().getSystem(), this);

    ActorRef child = getContext().actorOf(MyWork.props(), "restartActor");

    private static SupervisorStrategy strategy =
            new OneForOneStrategy(10, Duration.create(1, TimeUnit.MINUTES),
                    DeciderBuilder
                            .match(ArithmeticException.class, e -> SupervisorStrategy.resume())
                            .match(NullPointerException.class, e -> SupervisorStrategy.restart())
                            .match(IllegalArgumentException.class, e -> SupervisorStrategy.stop())
                            .matchAny(o -> SupervisorStrategy.escalate())
                            .build());

    @Override
    public SupervisorStrategy supervisorStrategy() {
        return strategy;
    }


    @Override
    public void onReceive(Object o) throws Throwable {
        unhandled(o);
    }

    public static void main(String[] args) {
        ActorSystem system = ActorSystem.create("strategy", ConfigFactory.load("akka.config"));
        ActorRef superVisor = system.actorOf(Props.create(OverrideHandler.class), "SuperVisor");

        ActorSelection actorSelection = system.actorSelection("akka://strategy/user/SuperVisor/restartActor");//这是akka的路径。restartActor是在SuperVisor中创建的。
        actorSelection.tell(MyWork.Msg.RESTART, ActorRef.noSender());
        //actorSelection.tell(MyWork.Msg.RESUME, ActorRef.noSender());

    }

}

Restart

当进行 restart 时,在 MyWork 中打印了uid和path,以及 Object 的 hash 值。可以看出,preStart 和 preRestart 在旧的实例 621249279 上调用,postRestart 在新实例上 1073815171 调用。

MyWork preStart uid=1650273805, path=akka://strategy/user/SuperVisor/restartActor, object hash=621249279
MyWork preRestart uid=1650273805, path=akka://strategy/user/SuperVisor/restartActor, object hash=621249279
MyWork postRestart uid=1650273805, path=akka://strategy/user/SuperVisor/restartActor, object hash=1073815171

Resume

当 resume 时,只有 preStart 被调用。

MyWork preStart uid=-357461364, path=akka://strategy/user/SuperVisor/restartActor, object hash=1763940324

Stop流程

节点 Stop 时,会先调用其所有子 actor 的 postStop() 方法。

示例代码:

import akka.actor.*;
import akka.event.Logging;
import akka.event.LoggingAdapter;
import cn.edu.tsinghua.akka.MyWork;

/**
 * 当前actor停止前,会先stop掉所有子actor。子actor的postStop()会在当前actor的postStop()之前被调用
 */
public class FatherActor extends AbstractActor {

    private final LoggingAdapter log = Logging.getLogger(getContext().getSystem(), this);


    @Override
    public void preStart() {
        System.out.println("Father preStart uid=" + getSelf().path().uid() + ", path=" + getSelf().path() + ", object hash=" + this.hashCode());
        getContext().actorOf(Props.create(MyWork.class), "second");
    }

    @Override
    public void postStop() {
        System.out.println("Father stopped uid=" + getSelf().path().uid() + ", path=" + getSelf().path() + ", object hash=" + this.hashCode());
    }

    @Override
    public Receive createReceive() {
        return receiveBuilder()
                .matchEquals("stop", s -> {
                    getContext().stop(getSelf());
                })
                .matchAny(o -> log.info("received unknown message"))
                .build();
    }

    public static void main(String[] args) {
        ActorSystem system = ActorSystem.create("testSystem");
        ActorRef first = system.actorOf(Props.create(FatherActor.class), "first");
        first.tell("stop", ActorRef.noSender());
    }
}

输出为:

Father preStart uid=-256137015, path=akka://testSystem/user/first, object hash=326381712
MyWork preStart uid=1593806360, path=akka://testSystem/user/first/second, object hash=4025049
MyWork stopped uid=1593806360, path=akka://testSystem/user/first/second, object hash=4025049
Father stopped uid=-256137015, path=akka://testSystem/user/first, object hash=326381712

顺便给上pom依赖,没有都用到

<dependency>
    <groupId>com.typesafe.akka</groupId>
    <artifactId>akka-actor_2.12</artifactId>
    <version>2.5.12</version>
</dependency>
<dependency>
    <groupId>com.typesafe.akka</groupId>
    <artifactId>akka-agent_2.12</artifactId>
    <version>2.5.12</version>
</dependency>
<dependency>
    <groupId>com.typesafe.akka</groupId>
    <artifactId>akka-cluster_2.12</artifactId>
    <version>2.5.12</version>
</dependency>

大家有兴趣的可以关注我的公众号(DBDeveloper),涉及分布式数据库、大数据和个人成长分享,欢迎大家一起交流进步

这里写图片描述

猜你喜欢

转载自blog.csdn.net/qiaojialin/article/details/80279516