[翻译]AKKA笔记 - ACTOR生命周期 - 基本 -5

news/2025/6/1 10:20:53

原文地址:http://rerun.me/2014/10/21/akka-notes-actor-lifecycle-basic/

(请注意这了讨论的生命周期并不包括 preRestart 或者postRestart方法,当我们讨论supervision时候我们会说这个)

基本的Actor生命周期很直观。除了一点小不同,你可以直接拿基本Actor生命周期与Java Servlet生命周期作比较。

  1. 像其他常规类一样,我们有一个构造函数。

  2. preStart方法会被调用。 这里你可以在postStop初始化一些稍后你想清理的资源。

  3. receive方法用作服务或者消息处理,占用了大部分时间。

先看下一个打印了生命周期的简单actor。

DUMB LIFECYCLE ACTOR

    package me.rerun.akkanotes.lifecycleimport akka.actor.{ActorLogging, Actor}  import akka.event.LoggingReceiveclass 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")}}

APP

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 shutdownThread.sleep(2000)actorSystem.shutdown()}

输出

Inside BasicLifecycleLoggingActor ConstructorActor[akka://LifecycleActorSystem/user/lifecycleActor#-2018741361]Inside the preStart method of BasicLifecycleLoggingActorhelloInside postStop method of BasicLifecycleLoggingActor  

那个在基础Actor生命周期与Servlet生命周期的一点不同是什么?

Actor生命周期中的构造函数和preStart是没什么不一样的。

我把context.self在构造函数中进行打印的原因就是 - 不像Servlets,Actor在构造函数中可以访问到ActorContext。而preStart与构造函数间的差别就很微妙了。如果你要打破砂锅问到底,我们再看下之前说的不同 - 当Actor重启时(失败的case)调用preStart是可控的。 用构造函数就不可能了。

什么时候POSTSTOP会被调用?

像我们前面看到的程序, postStrop在ActorSystem关闭时会被调用。还有很多其他的机会能调用到这个回调。

1.ACTORSYSTEM.STOP()

我们可以用ActorSystem的stop方法来停止一个ActorActorContext

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)或无原因的把自己杀掉(这只是为了好玩。没有一个有追求的Actor会这么做)

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)消息到目标actor来达到同样的目的。请记住这个毒药消息,会像前面的stop消息一样被放在常规mailbox中,当被处理到的时候才会运行。

object LifecycleApp extends App{val actorSystem=ActorSystem("LifecycleActorSystem")val lifecycleActor=actorSystem.actorOf(Props[BasicLifecycleLoggingActor],"lifecycleActor")lifecycleActor!PoisonPill......

4.KILL

除了发送一个毒药(PoisonPill), 你也可以给目标Actor发送一个kill消息。

lifecycleActor ! Kill  

发送毒药消息和kill消息,区别很微妙但很重要。

  1. PoisonPill,一个Terminated消息会被发送到所有的watcher(稍后我们会在DeathWatch章节中看到)

  2. 发送kill消息,宿主Actor会抛出一个ActorKilledException并被发送给Supervisor(稍后我们会在Supervision章节中看到)


细枝末节

我前面说的常规mailbox是啥意思?是否还有个“特别”mailbox?是的,确实有!我们会在讨论supervision和system消息时说到这个。


TERMINATION

当Actor停止时,他会进入一个Terminated状态。你马上就会想到一个问题,那些发到一个已经是terminated状态的Actor的消息会怎么样?

让我们看看:

APP

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}

ACTOR - 与之前一样

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 [java.lang.String] 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有一些引用。任何你发给那个已经terminated的Actor的消息都会转发给一个叫DeadLetterActor的内部Actor的mailbox。


那么这之后又发生了什么?

DeadLetter Actor处理它mailbox里的消息,把每个消息都封装成一个DeadLetter并且把它发布到EventStream中。

另一个叫DeadLetterListener的Actor消费所有的DeadLetter并把它输出成日志消息。从这里看。

记住,当我们说日志的时候,我们可以看到所有输出到EventStream的消息并且可以随意消费 - 只是这个消费者一样必须是个Actor。让我们试试。

在我们的例子中,我们消费EventStream并且观看所有DeadLetter消息最后打印到console(这没有创造力??)当然,我们还能自由的做任何事如生成告警,把它保存到数据库或把它拿去作分析。

订阅EVENTSTREAM的DEADLETTERS

import akka.actor.ActorSystem  
import akka.actor.Props  
import akka.actor.PoisonPill  
import akka.actor.DeadLetter  
import akka.actor.Actorobject 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 [java.lang.String] 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://blog.csdn.net/weixin_34336526/article/details/89369511
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:https://dhexx.cn/news/show-566087.html

相关文章

初识C++之AVL树

目录 一、AVL树的概念 二、模拟实现一个AVL树 1.结构体定义 2.更新平衡因子 3.旋转子树 3.1 新节点插入较高右子树的右侧——右右->左单旋 3.2 插入较高左子树的左侧——右右->右单旋 3.3 插入较高右子树的左侧节点——右左->右左双旋 3.4 在左子树的右侧插入…

MySQL出现Waiting for table metadata lock的原因以及解决方法

转自:http://ctripmysqldba.iteye.com/blog/1938150 (有修改) MySQL在进行alter table等DDL操作时,有时会出现Waiting for table metadata lock的等待场景。而且,一旦alter table TableA的操作停滞在Waiting for table metadata lock的状态&a…

二分算法

二分查找函数 写一个函数BinarySearch,在包含size个元素的、从小到大排序的int数组a里查找元素p,如果找到则返回元素下标,如果找不到,则返回-1. int BinarySearch(int a[],int size,int p) {int L0;//查找区间的左端点int Rsize-1…

数据包的接收过程

网络栈的层次结构: 我们就从最底层开始追溯一个数据包的传递流程。 1、网络接口层 * 硬件监听物理介质,进行数据的接收,当接收的数据填满了缓冲区,硬件就会产生中断,中断产生后,系统会转向中断服务子程序。…

aes 128、192、256位,cbc、cfb、ecb、ofb、pcbc加密解密

2019独角兽企业重金招聘Python工程师标准>>> ####AES 128/192/256位CBC/CFB/ECB/OFB/PCBC加密解密在线计算 ###AES加解密总共有以下这些 算法/模式/填充 字节加密后数据长度 不满16字节加密后长度 AES/CBC/NoPadding 16 …

windows下svn钩子实现每次提交更新至web目录

目的 找 到SVN Server中的仓库(Repositories)文件夹的位置,在相应的项目文件夹中找到hooks文件夹。在该文件夹中添加一个post- commit文件;当有commit动作发生时(提交到SVN Server时)就会执行这个post-comm…

计算机学院举办 温暖冬日 感恩社会 活动,爱心暖瓶贴 温情暖冬日——马克思主义学院青年志愿者协会开展爱心暖瓶贴特色志愿活动...

正值寒冬时节,为了更好地给学校全体成员送去温暖与关怀,营造温馨、友爱的校园氛围,2020年12月7日至12月9日,马克思主义学院青年志愿者协会在校园内开展爱心暖瓶贴特色志愿服务活动。活动开始前,志愿者们已经做好了分工…

javaweb之javascript结合(三)

1、案例一:在末尾添加节点第一步:获取到ul标签第二步:创建li标签document.createElement("标签名称")方法第三步:创建文本document.createTextNode("文本内容");第四步:把文本添加到li下面使用 ap…

注意指针修饰符的准确含义

首先从一起多线程无锁算法的事故说起,以下是一个无锁栈的实现测试,但在开-O2以上优化的情况下它却无法正常工作: #include "lf_stack.h" #include "kn_list.h" #include "kn_time.h" #include "kn_thread.h" #include "kn_atomic…

计算机应用基础第5次作业,2014春浙大远程计算机应用基础第5次作业5.Powerpoint知识题...

C.保存对话框中的保存类型选择为"模板"D.保存(或另存为)对话框中的保存类型选择为"Powerpoint放映"[解析]略19、在PowerPoint中需要帮助时,可以按功能键___A___。A.[F1] --- 一个程序一般都使用F1作为启动“帮助信息”…