zoukankan      html  css  js  c++  java
  • akka设计模式系列-actor锚定

      actor锚定模式是指使用actorSelection对acor进行锚定的设计模式,也可以说是一个对actor的引用技巧。在某些情况下,我们可能需要能够根据Actor的path锚定对应的实例。简单来说就是,无论actor是因为异常导致的restart还是用户主动stop,然后再重新actorOf,只要actor的路径和name相同,我们都希望把消息发送给改Actor的一个实例。那我们来看一下actorSelection和ActorRef的使用区别。

    class AnchorActor extends Actor{
      override def preStart(): Unit = {
        super.preStart()
        println(s"self=$self,path=${self.path}")
      }
      override def receive: Receive = {
        case any =>
          println(s"Hello $any")
      }
    }
    object AnchorPattern{
      def main(args: Array[String]): Unit = {
        val system = ActorSystem("AnchorPattern",ConfigFactory.load())
        val anchorActor = system.actorOf(Props(new AnchorActor),"anchorActor")
        anchorActor ! 1
        val anchorActorSelection = system.actorSelection("/user/anchorActor")
        anchorActorSelection ! 2
        system.stop(anchorActor)
        // 等待anchorActor彻底stop
        Thread.sleep(3*1000)
        system.actorOf(Props(new AnchorActor),"anchorActor")
        anchorActor ! 3
        anchorActorSelection ! 4
    
      }
    }
    

    输出:

    self=Actor[akka://AnchorPattern/user/anchorActor#-1941442858],path=akka://AnchorPattern/user/anchorActor
    Hello 1
    Hello 2
    self=Actor[akka://AnchorPattern/user/anchorActor#489200584],path=akka://AnchorPattern/user/anchorActor
    Hello 4
    [INFO] [07/31/2018 16:59:48.102] [AnchorPattern-akka.actor.default-dispatcher-5] [akka://AnchorPattern/user/anchorActor] Message [java.lang.Integer] without sender to Actor[akka://AnchorPattern/user/anchorActor#-1941442858] was not delivered. [1] dead letters encountered. If this is not an expected behavior, then [Actor[akka://AnchorPattern/user/anchorActor#-1941442858]] may have terminated unexpectedly, This logging can be turned off or adjusted with configuration settings 'akka.log-dead-letters' and 'akka.log-dead-letters-during-shutdown'.
    

       上面代码中,我们创建了一个AnchorActor实例,然后通过ActorRef和ActorSelection分别给AnchorActor发送了两条消息,anchorActor都收到了。之后我们把之前的AnchorActor实例给stop掉,再ActorRef和ActorSelection分别发送消息,由输出我们可以看出,第二次发消息时,只有anchorActorSelection发送成功了。这就证明了,ActorRef只能指向Actor的某个特定实例;而ActorSelection通过路径指向Actor的所有实例,即使该actor的实例被销毁然后重新创建,ActorSelection也能指向新的实例。

      我这篇博客把ActorSelection发消息成为actor锚定模式,主要是想告诉读者ActorSelection与ActorRef的区别。那读者可能会问,既然ActorSelection可以对actor进行锚定,能指向最新的实例,为什么还要有ActorRef存在的必要呢?其实这要区别对待,结合场景来谈具体使用哪种形式。如果你的业务场景下,不区分Actor的实例,只要路径和name相同,就把所有的消息发送给它,那就是用ActorSelection;如果你的场景需要严格区分Actor的实例,比如不同的实例就代表不同的服务对象,不同服务对象的结果是不同的,此时就需要用ActorRef来通信。另外ActorSelection是无法保证对应路径的actor存在的,也就是说ActorSelection可能会把消息发送到deadLetters,而开发者是无法知道的;ActorRef一旦存在就可以发送消息,对方的Actor一定存在,当然消息也可能无法送达,比如对方的actor被stop掉或者网络故障。

      虽然这个设计模式比较简单,但希望读者能够严格区分二者的关系,在合适的场景使用合适的技术。

  • 相关阅读:
    【学习笔记】ASP.NET页面之间传值的方式之Application
    【学习笔记】ASP.NET页面之间传值的方式之QueryString
    【学习笔记】C#中的装箱(inboxing)和拆箱(unboxing)
    C# Func和Action用法以及区别和使用Lambda表达式
    构建ABP vNext项目并切换MySql数据库
    .Net FrameWork发布项目时报Microsoft.Net.Compilers is only supported on MSBuild v16.3 and above错误解决方案
    Docker容器与Linux主机环境获取时间不一致
    shell脚本中无法使用cd的问题解决方法
    Docker安装Mysql8.0,并配置忽略大小写
    Docker-Compose排版一些坑
  • 原文地址:https://www.cnblogs.com/gabry/p/9397078.html
Copyright © 2011-2022 走看看