第102讲:通过案例解析Akka中的Actor运行机制以及Actor的生命周期

Actor是构建akka程序的核心基石,akka中actor提供了构建可伸缩的,容错的,分布式的应用程序的基本抽象,

actor是异步的,非阻塞式的,事件驱动的轻量级的模型,

actor中都有自己的成员,也有receive方法,在receive中处理具体的逻辑。

actor间沟通只能通过发消息。

!发消息是异步的过程,MasterActor只会对自己的邮箱感兴趣,不断循环自己的邮箱,

收到消息后进行处理。

在actor内部创建其他actor是通过ActorSystem.ActorOf(Props[MasterActor])

创建出工作的actor后,actor就进入start状态,开始查看邮箱中是否有邮件,

有邮件时就处理邮件,直到收到停止的指令。

Actor的生命周期:

1)初始化:preStart

2)接收消息、处理消息。用模式匹配的方式匹配到消息就处理

3)stop处理消息进行清理工作。

为什么会出现preRestart/postRestart呢?

如actor崩溃了(exception),被supervisor重新启动时,preRestart/postRestart就会被调用,进行状态恢复

创建actor有多种方式,如ActorSystem,接下来讲解其他方式。

第103讲:通过案例解析Akka中的Actor的定义和创建

第104讲:通过案例解析Akka中的Actor的不同类型的Constructor

actor的构造器有两种:

1默认:构造时把actor具体的类名称传入

2非:构造实例时传入参数,助于特殊初始化,

如可以在构造器中传入其他actor的actorRef(引用),这样就可以在自己的receive中

给其他actor发消息。

val aggregateActor:ActorRef = context.actorOf(Props[AggregateActor],name="aggregate")

构造默认构造器

val reduceActor:ActorRef = context.actorOf(Props(new ReduceActor(aggregateActor)),name="reduce")

构造非默认构造器

源码:

/**

* Strores the context for this actor, including self , and sender.

* It is implicit to support operations such as 'forward'.

*/

protected[akka] implicit val context:ActorContext = {

val contextStack = ActorCell.contextStack.get

...

}

implicit final val self = context.self  //MUST BE A VAL, TRUST ME

使用context.actorOf可以构建具体的actor的实例并拿到实例的句柄

def actorOf(props:Props,name:String):ActorRef

第105讲:解析Akka中的子Actor及其代码

akka中为什么会有子actor

因为akka中的actor是分层结构的,任何actor在akka中都属于具体的层次。

为什么需要子actor,什么时候需要应该创建子actor

1当任务有多个子任务时

2某actor由父acotr执行时可能 比较容易出错,将具体任务进行隔离。

因为使用子actor时,当子actor崩溃时,可通过监控actor进行恢复

当然通过actor创建了子actor,子actor可将任务委派给下一个actor,

可能有人认为创建actor会占用巨大资源,事实上,基于优良的架构,

创建acotr代价远远小于线程的创建。

val _system = ActorSystem("HelloAkka")    //通过actorSystem创建具体的actor的容器:HelloAkka

val master = _system.actorOf(Props[MasterActor],name="master"    //master是HelloAkka的子actor。

println(master.path)

上述代码打印结果:

akka://HelloAkka/user/master

akka://是固定的协议,与http协议一样。

HelloAkka是创建的actorSystem的具体的名称

user是根目录下创建的所有actor的上一级目录,除user外还有system

可以看出akka是层级结构。

val aggregateActor:ActorRef = context.actorOf(Props[AggregateActor],name="aggregate")

val reduceActor:ActorRef = context.actorOf(Props(new ReduceActor(aggregateActor)),name="reduce")

val mapActor:ActorRef = context.actorOf(Props(new MapActor(reduceActor)),name="map")

println(aggregateActor.path)

println(reduceActor.path)

println(mapActor.path)

打印结果:

akka://HelloAkka/user/master/aggregate

akka://HelloAkka/user/master/reduce

akka://HelloAkka/user/master/map

第106讲:解析Akka中的消息的不同发送方式方式详解学习笔记

akka中有两种消息发送方式:

1.发送后立即忘记(Fire and Forget)

2.发送消息后等待目标actor回复(Send and Receive)

所有消息都是immutable(不可变的),异步的。

发送消息的方法:java是tell,scala是!

第107讲:Akka中的Future使用代码实战详解

本讲分享akka中消息发送的第二种方式:send and receive

给actor发送消息后会等待目标actor的回复

用future等待目标actor的回复

actorA ask actorB,用future来接收actorB的内容。

接收到future后可以提取出future的内容。

FutrueActor

package akka.dt.app.actors

import akka.actor.Actor

/**
* 描述:
* 作者: sunrunzhi
* 时间: 2018/11/15 14:18
*/
class FutureActor extends Actor{ def receive:Receive={
case message:String=>{
Thread.sleep(3000)
println(Thread.currentThread().getName+" is going to work!!!")
println("The content of the received message is :"+message)
this.sender() ! "Power comes from Love!"+this.self
println("The sender path="+this.sender().path)
context.stop(this.self)
println(this.self.path) } }
}

ActorWithFuture:

package akka.dt.app.future

import akka.actor.{ActorRef, ActorSystem, Props}
import akka.dt.app.actors.FutureActor
import akka.pattern.Patterns
import akka.util.Timeout import scala.concurrent.duration.Duration
import scala.concurrent.{Await, Future} /**
* 描述:ActorWithFuture
* 作者: sunrunzhi
* 时间: 2018/11/15 13:58
*/
object ActorWithFuture { def main(args: Array[String]): Unit = { println(Thread.currentThread().getName)
//创建ActorSystem容器
val Fsystem=ActorSystem("FutrueSystem")
val worker:ActorRef=Fsystem.actorOf(Props[FutureActor],name="future")
//等待超时时间
val timeout:Timeout=new Timeout(Duration.create(5,"second"))
//通过ask发消息到worker,等待worker回复内容
val futrue:Future[AnyRef]=Patterns.ask(worker,"For free, for everyone,forever,for love",timeout)
//通过Await.result的等待future结果
val result=Await.result(futrue,timeout.duration)
println("result:"+result) } }

第108讲:Akka中的Actor消息的处理、消息回复、消息转发 

本讲主要讲解:

1.Actor消息的处理

2.Actor消息的回复

3.Actor消息的转发

处理消息一般通过复写receive方法,通过模式匹配的方式。

/**

* This defines the initial actor behavior, it must return a partial function

* with the actor logic.

*/

Protected def receive: Receive

如果要回复消息给发送者的话要获得发送者的actorRef,

就是说代理的句柄。Akka中提供了sender这个ActorRef指向当前收到的消息的发送者。但这有一个风险:消息到当前actor后,它的发送者已不存在了,这时给sender回复消息时,此时的消息就会变成deadLetters。

/**

* The reference sender Actor of the last received message.

* Is defined if the message was sent from another Actor,

* else ‘deadLetters’ in [[akka.actor.ActorSystem]].

*/

Final def sender: ActorRef = context.sender

消息的转发:

Forward的方式。

mapActor.forward(message)

Forward的源码:

/**

* Forwards the message and passer the original sender actor as the sender.

* Works with ! And ?/ask

Def forward(message: Any)(implicit context: ActorContext) = tell(message,context.sender)

第109讲:Akka中的Actor异步和同步停止方式实战详解学习笔记

本讲内容:

1.Actor异步停止方式

2.Actor同步停止方式

为什么要停止actor?

Actor完成了自己的消息处理任务后,后续不再需要这个actor再继续处理工作,为了节省或回收系统资源,就有必须停止actor

Actor在正式处理邮箱中具体的邮件以前会有preStart,在preStart中进行资源的初始化,如连接网络或连接数据库或打开文件。在处理完毕邮件后,actor生命周期的最后会有环节,会有postStop,在postStop中可以进行关闭网络关闭数据库或关闭文件的句柄,在akka中要想停止 actor有多种方式:同步、异步,但都需要postStop,在postStop中进行资源回复的操作。

在postStop调用时会在内部在akka继承树上产生操作,任务完成后邮箱中的内容不会再被处理,同时会有一个具体消息叫deathWatch的消息发出,通知supervisor说自己停止了。在akka中要停止actor会有多种不同方式:

1.停止actorSystem,

/**

* Stop this actor system.This will stop the guardian actor, which in turn will recurisiverly stop all its child actor, then the system guardian (below which the logging actor reside) and the execute all registered termination handlers (See [[ActorSystem.registerOnTermination]]).

*/

Def shutdown(): Unit

停止一个actor后,其子actor会全部被停止。

2.其他方式停止actor:异步操作。

Master ! Poisonpill  //异步

Master ! Kill //同步

_system.shutdown

Context.stop(self)  //也可以停止其他actor。

第110讲:Akka中的Actor的Monitoring初步解析

本讲主要讲解actor的监控机制

这和supervisor不同。

Akka是由树状结构构成的分层结构。

下层actor发生变化上层actor都可以感知到变化。

假设stop上层actor时,下层actor会首先被stop,然后才是上层actor。

Monitor actor会监控worker actor,如果worker actor被中断,monitor actor会感知到这个事件,并采取适当的action,如再次启动一个worker actor实例,继续完成同样的工作。

这在实际开发系统时非常重要,开发系统,具体actor可能会工作不稳定,或硬件软件因素被意外或意料中的停止,而被中断的工作还要继续,所以需要monitor actor监控。

Monitor actor是通过context.watch来监控worker actor的。

当worker actor被停止时,会有terminated消息发送给monitor actor,monitor actor收到消息时会采取一定措施。如启动一个同样的actor。这样其他actor就可以继续给这个actor发消息了。

第111讲:Akka中的Actor中用become和unbecome动态切换receive的具体处理逻辑实战

本期内容:

1.动态切换actor处理逻辑分析

2.Become和unbecome代码实战

可以改变actor具体处理业务逻辑的代码,而且是动态改变。

可以借助akka提供的become和unbecome机制动态地切换当前actor的处理逻辑。

代码:

Case class Spark

Case class Flink

Class SparkFlinkActor extends Actor {

import context._

var cont = 0

def receive: Receive = {

case Spark =>

println(“Here is Spark!!!”)

count = count + 1

Thread.sleep(100)

self ! Flink  //receive在收到Flink消息后就会直接进入become内

become {  //把处理代码切换成become内的逻辑

//become之前的代码在become出现后就不再存在了

case Flink =>

println(“Here is Flink!!!”)

count = count +1

Thread.sleep(100)

self ! Spark

unbecome()    //把代码处理逻辑切换一次,把become代码从堆栈中弹出。

}

if(count > 10) countext.stop(self)

}

}

object MyActorSystem {

def main(args: Array[String]): Unit = {

val _system = ActorSystem(“BecomeUnbecome”)

val sparkFlinkActor = _system.actorOf(Props[SparkFlinkActor])

sparkFlinkActor ! Spark

Thread.sleep(2000)

_system.shutdown

}

}

Scala零基础教学【102-111】Akka 实战-深入解析的更多相关文章

  1. Scala零基础教学【1-20】

    基于王家林老师的Spark教程——共计111讲的<Scala零基础教学> 计划在9月24日内完成(中秋节假期之内) 目前18号初步学习到25讲,平均每天大约完成15讲,望各位监督. 初步计 ...

  2. Scala零基础教学【81-89】

    第81讲:Scala中List的构造是的类型约束逆变.协变.下界详解 首先复习四个概念——协变.逆变.上界.下界 对于一个带类型参数的类型,比如 List[T]: 如果对A及其子类型B,满足 List ...

  3. Scala零基础教学【61-80】

    第61讲:Scala中隐式参数与隐式转换的联合使用实战详解及其在Spark中的应用源码解析 第62讲:Scala中上下文界定内幕中的隐式参数与隐式参数的实战详解及其在Spark中的应用源码解析 /** ...

  4. Scala零基础教学【90-101】Akka 实战-代码实现

    第90讲:基于Scala的Actor之上的分布式并发消息驱动框架Akka初体验 akka在业界使用非常广泛 spark背后就是由akka驱动的 要写消息驱动的编程模型都首推akka 下面将用30讲讲解 ...

  5. Scala零基础教学【41-60】

    第41讲:List继承体系实现内幕和方法操作源码揭秘 def main(args: Array[String]) { /** * List继承体系实现内幕和方法操作源码揭秘 * * List本身是一个 ...

  6. Scala零基础教学【21-40】

    第24讲:Scala中SAM转换实战详解 SAM:single abstract method 单个抽象方法   我们想传入一个函数来指明另一个函数具体化的工作细节,但是重复的样板代码很多. 我们不关 ...

  7. [转]小D课堂 - 零基础入门SpringBoot2.X到实战_汇总

    原文地址:https://www.cnblogs.com/wangjunwei/p/11392825.html 第1节零基础快速入门SpringBoot2.0 小D课堂 - 零基础入门SpringBo ...

  8. 小D课堂 - 零基础入门SpringBoot2.X到实战_汇总

    第1节零基础快速入门SpringBoot2.0 小D课堂 - 零基础入门SpringBoot2.X到实战_第1节零基础快速入门SpringBoot2.0_1.SpringBoot2.x课程介绍和高手系 ...

  9. 小D课堂 - 零基础入门SpringBoot2.X到实战_第1节零基础快速入门SpringBoot2.0_1、SpringBoot2.x课程介绍和高手系列知识点

    1 ======================1.零基础快速入门SpringBoot2.0 5节课 =========================== 1.SpringBoot2.x课程全套介绍 ...

随机推荐

  1. 帮助小伙伴写的组装xml字符串类

    import java.io.IOException; import java.io.StringWriter; import java.util.ArrayList; import java.uti ...

  2. 使用Frida简化Android端应用安全测试

    @author : Dlive 在对Android应用进行Web漏洞测试时,经常遇到一种情况:HTTP传输的数据带有签名字段 处理这种情况的方法通常是逆向签名算法,但是如果算法在so中,而且so加壳了 ...

  3. Swift “ambiguous use of operator '>'”

    http://stackoverflow.com/questions/25458548/swift-ambiguous-use-of-operator 3down votefavorite   I h ...

  4. DDD——让天下没有难调的程序

    https://www.linuxidc.com/Linux/2016-11/137343.htm DDD全称Data Display Debugger,当我第一次见到它时,它的界面着实让我吃了一惊, ...

  5. servlet(2) - 利用MyEclipse新建一个servlet - 小易Java笔记

    1.Tomcat在MyEclipse中集成 ==> Window-preferences-MyEclipse-Servers-Tomcat-Tomcat 6.x-点击右侧的Browse,选择你的 ...

  6. ES6新特性之傻瓜式说明

    ES6出来挺长一段时间了,但目前网上好像教程并不多也不详细.我依然遵循傻瓜式教学模式,白话文说明JavaScript和ES6的一些区别,说明下ES6的一些新特性.本文适合新手学习,大神请勿见笑,在下在 ...

  7. 取消SecureCRT的右击粘贴功能

    默认为选中时自动复制,右键粘贴 要取消的话在: Options->Global Options ...->Terminal 里面有个Mouse的选项块. Paste on Right/Le ...

  8. UVALive - 5844

    题是pdf版 Sample Input23mississippinni55i55ippi2foobar|=o08arSample Output10 /** 题意:给出一个normal串,一个leet串 ...

  9. Selenium2+python自动化51-unittest简介【转载】

    前言 熟悉java的应该都清楚常见的单元测试框架Junit和TestNG,这个招聘的需求上也是经常见到的.python里面也有单元测试框架-unittest,相当于是一个python版的junit. ...

  10. docker从零开始(四)集群初体验,docker-machine swarm

    介绍 在第三节中,选择了第二节中编写的应用程序,并通过将其转换为服务来定义它应如何在生产中运行,并生成五个应用实例 在本节中,将此应用程序部署到群集上,在多台计算机上运行它.多容器,多机应用程序通过连 ...