Akka笔记–演员生命周期–基本– 5

(请注意,此生命周期文章不涉及preRestartpostRestart方法。我们在讨论监督时将讨论它们)

Actor的基本生命周期非常直观。 实际上,您可以将基本Actor生命周期与Java servlet生命周期进行比较,但有一个特殊的区别。

  1. 就像任何其他常规类一样,我们有一个构造函数
  2. preStart将调用preStart方法。 在这里,您可以初始化要在postStop清理的postStop
  3. receive方法的“服务”或消息处理占用了大部分时间,并且这之间发生了。

让我们看一个打印生命周期的简单actor。

傻瓜生命周期演员

package me.rerun.akkanotes.lifecycle

import akka.actor.{ActorLogging, Actor}  
import akka.event.LoggingReceive

class BasicLifecycleLoggingActor extends Actor with ActorLogging{

  log.info ("Inside BasicLifecycleLoggingActor Constructor")
  log.info (context.self.toString())
  override def preStart() ={
    log.info("Inside the preStart method of BasicLifecycleLoggingActor")
  }

  def receive = LoggingReceive{
    case "hello" => log.info ("hello")
  }

  override def postStop()={
    log.info ("Inside postStop method of BasicLifecycleLoggingActor")
  }

}

应用程式

LifecycleApp只是启动,向Actor发送消息并关闭ActorSystem。

import akka.actor.{ActorSystem, Props}

object LifecycleApp extends App{

  val actorSystem=ActorSystem("LifecycleActorSystem")
  val lifecycleActor=actorSystem.actorOf(Props[BasicLifecycleLoggingActor],"lifecycleActor")

  lifecycleActor!"hello"

  //wait for a couple of seconds before shutdown
  Thread.sleep(2000)
  actorSystem.shutdown()

 }

输出量

Inside BasicLifecycleLoggingActor Constructor

Actor[akka://LifecycleActorSystem/user/lifecycleActor#-2018741361]

Inside the preStart method of BasicLifecycleLoggingActor

hello

Inside postStop method of BasicLifecycleLoggingActor
Servlet和基本Actor生命周期之间的特殊区别是什么?

Actor生命周期中的构造函数和preStart之间没有区别–或多或少。

我之所以在构造函数中打印context.self是因为–与Servlet不同,Actor甚至可以在构造函数内部访问ActorContext 。 这样,preStart和构造函数之间的区别就变得非常微妙。 在讨论监督时,我们将重新讨论两者之间的区别,但是,如果您好奇,可以控制Actor重新启动时(如果发生故障)调用preStart 。 使用构造函数,这是不可能的。

什么时候调用postStop?

当我们从程序所看到的, postStop被调用时ActorSystem关闭。 还有两次回调也被调用。

1. ActorSystem.stop()

我们可以使用ActorSystemActorContextstop方法stop ActorContext

object LifecycleApp extends App{

  val actorSystem=ActorSystem("LifecycleActorSystem")
  val lifecycleActor=actorSystem.actorOf(Props[BasicLifecycleLoggingActor],"lifecycleActor")

  actorSystem.stop(lifecycleActor);

  ...
  ...

}

2. ActorContext.stop

1)通过消息(外部或自身传递消息)
class BasicLifecycleLoggingActor extends Actor with ActorLogging{  
...
...
  def receive = LoggingReceive{
    case "hello" => log.info ("hello")
    case "stop" => context.stop(self)
  }

object LifecycleApp extends App{

  val actorSystem=ActorSystem("LifecycleActorSystem")
  val lifecycleActor=actorSystem.actorOf(Props[BasicLifecycleLoggingActor],"lifecycleActor")


  lifecycleActor!"stop"
...
...
2)或无故自杀

(这只是为了好玩。没有志向的演员会这样做)

class BasicLifecycleLoggingActor extends Actor with ActorLogging{

  log.info ("Inside BasicLifecycleLoggingActor Constructor")
  log.info (context.self.toString())
  context.stop(self)
  ...
  ...

3.毒丸

在上一个示例中,我们从LifecycleApp向Actor传递了一条名为stop的消息。 Actor收到了该消息,并使用context.stop杀死了自己。 通过将PoisonPill消息传递给目标参与者,我们可以实现相同的目的。 请注意, PoisonPill消息与上一个停止消息一样,被放入常规邮箱中,并且在出现时会被处理。

object LifecycleApp extends App{

  val actorSystem=ActorSystem("LifecycleActorSystem")
  val lifecycleActor=actorSystem.actorOf(Props[BasicLifecycleLoggingActor],"lifecycleActor")

  lifecycleActor!PoisonPill
  ...
  ...
琐事

普通邮箱是什么意思? 也有一个“特殊”邮箱吗? 对。 有。 当我们讨论监督和system消息时,我们将进行讨论。

终止

一旦Actor停止,就可以进入Terminated状态。 您想到的直接问题是,发送到已终止的Actor的消息将发生什么情况?

让我们来看看:

应用程式

object LifecycleApp extends App{

  val actorSystem=ActorSystem("LifecycleActorSystem")
  val lifecycleActor=actorSystem.actorOf(Props[BasicLifecycleLoggingActor],"lifecycleActor")

  lifecycleActor!"hello"
  lifecycleActor!"stop"
  lifecycleActor!"hello" //Sending message to an Actor which is already stopped

}

演员–和以前一样

class BasicLifecycleLoggingActor extends Actor with ActorLogging{

  def receive = LoggingReceive{
    case "hello" => log.info ("hello")
    case "stop" => context.stop(self)

  }
}

输出量

BasicLifecycleLoggingActor - hello 

akka.actor.RepointableActorRef - Message  from Actor[akka://LifecycleActorSystem/deadLetters] to Actor[akka://LifecycleActorSystem/user/lifecycleActor#-569230546] was not delivered. [1] dead letters encountered. This logging can be turned off or adjusted with configuration settings 'akka.log-dead-letters' and 'akka.log-dead-letters-during-shutdown'.

从日志中,您可以看到有一些关于deadletters参考。 您发送给已终止的Actor的任何消息都将转发到内部 Actor的邮箱,称为DeadLetterActor


下一步会发生什么?

DeadLetter Actor处理其邮箱中的消息,将每个消息包装为DeadLetter并将其发布到EventStream

另一个称为DeadLetterListener的 Actor使用所有DeadLetter并将其作为日志消息发布。 检查一下

记住,当我们谈论日志记录时 ,我们看到所有日志消息都已发布到EventStream上 ,并且我们可以自由订阅该EventStream -只是订阅者也需要是一个Actor。 让我们现在尝试。

在我们的示例中,我们将订阅EventStream并注意所有DeadLetter消息,并将其打印到控制台(对于创造力而言意义重大!!!)。 坦白说,我们可以自由地执行任何操作,从生成警报,将警报存储到数据库甚至馈送至分析。

订阅事件流

import akka.actor.ActorSystem  
import akka.actor.Props  
import akka.actor.PoisonPill  
import akka.actor.DeadLetter  
import akka.actor.Actor

object LifecycleApp extends App {

  val actorSystem = ActorSystem("LifecycleActorSystem")
  val lifecycleActor = actorSystem.actorOf(Props[BasicLifecycleLoggingActor], "lifecycleActor")

  val deadLetterListener = actorSystem.actorOf(Props[MyCustomDeadLetterListener])
  actorSystem.eventStream.subscribe(deadLetterListener, classOf[DeadLetter])

  lifecycleActor ! "hello"
  lifecycleActor ! "stop"
  lifecycleActor ! "hello"

}

class MyCustomDeadLetterListener extends Actor {  
  def receive = {
    case deadLetter: DeadLetter => println(s"FROM CUSTOM LISTENER $deadLetter")
  }
}
输出量
164  [LifecycleActorSystem-akka.actor.default-dispatcher-4] INFO  BasicLifecycleLoggingActor - hello 

167  [LifecycleActorSystem-akka.actor.default-dispatcher-4] INFO  akka.actor.RepointableActorRef - Message  from Actor[akka://LifecycleActorSystem/deadLetters] to Actor[akka://LifecycleActorSystem/user/lifecycleActor#-782937925] was not delivered. [1] dead letters encountered. This logging can be turned off or adjusted with configuration settings 'akka.log-dead-letters' and 'akka.log-dead-letters-during-shutdown'. 

FROM CUSTOM LISTENER DeadLetter(hello,Actor[akka://LifecycleActorSystem/deadLetters],Actor[akka://LifecycleActorSystem/user/lifecycleActor#-782937925])

翻译自: https://www.javacodegeeks.com/2014/10/akka-notes-actor-lifecycle-basic-5.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值