Scala零基础教学【102-111】Akka 实战-深入解析
第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 实战-深入解析的更多相关文章
- Scala零基础教学【1-20】
基于王家林老师的Spark教程——共计111讲的<Scala零基础教学> 计划在9月24日内完成(中秋节假期之内) 目前18号初步学习到25讲,平均每天大约完成15讲,望各位监督. 初步计 ...
- Scala零基础教学【81-89】
第81讲:Scala中List的构造是的类型约束逆变.协变.下界详解 首先复习四个概念——协变.逆变.上界.下界 对于一个带类型参数的类型,比如 List[T]: 如果对A及其子类型B,满足 List ...
- Scala零基础教学【61-80】
第61讲:Scala中隐式参数与隐式转换的联合使用实战详解及其在Spark中的应用源码解析 第62讲:Scala中上下文界定内幕中的隐式参数与隐式参数的实战详解及其在Spark中的应用源码解析 /** ...
- Scala零基础教学【90-101】Akka 实战-代码实现
第90讲:基于Scala的Actor之上的分布式并发消息驱动框架Akka初体验 akka在业界使用非常广泛 spark背后就是由akka驱动的 要写消息驱动的编程模型都首推akka 下面将用30讲讲解 ...
- Scala零基础教学【41-60】
第41讲:List继承体系实现内幕和方法操作源码揭秘 def main(args: Array[String]) { /** * List继承体系实现内幕和方法操作源码揭秘 * * List本身是一个 ...
- Scala零基础教学【21-40】
第24讲:Scala中SAM转换实战详解 SAM:single abstract method 单个抽象方法 我们想传入一个函数来指明另一个函数具体化的工作细节,但是重复的样板代码很多. 我们不关 ...
- [转]小D课堂 - 零基础入门SpringBoot2.X到实战_汇总
原文地址:https://www.cnblogs.com/wangjunwei/p/11392825.html 第1节零基础快速入门SpringBoot2.0 小D课堂 - 零基础入门SpringBo ...
- 小D课堂 - 零基础入门SpringBoot2.X到实战_汇总
第1节零基础快速入门SpringBoot2.0 小D课堂 - 零基础入门SpringBoot2.X到实战_第1节零基础快速入门SpringBoot2.0_1.SpringBoot2.x课程介绍和高手系 ...
- 小D课堂 - 零基础入门SpringBoot2.X到实战_第1节零基础快速入门SpringBoot2.0_1、SpringBoot2.x课程介绍和高手系列知识点
1 ======================1.零基础快速入门SpringBoot2.0 5节课 =========================== 1.SpringBoot2.x课程全套介绍 ...
随机推荐
- Spring securiuty 过滤器
1. HttpSessionContextIntegrationFilter 位于过滤器顶端,第一个起作用的过滤器. 用途一,在执行其他过滤器之前,率先判断用户的session中是否已经存在一个Sec ...
- Idea IntelliJ远程调试教程
总结 第一步:修改startup.sh 在倒第二行加上export JPDA_ADDRESS=8787 最后一行在start前面加上" jpda " 第二步:配置Idea, ...
- 51nod 1020 逆序排列——dp
在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序.一个排列中逆序的总数就称为这个排列的逆序数. 如2 4 3 1中,2 1,4 3,4 1,3 1是逆序 ...
- HDU 2036 改革春风吹满地 (数学)
题目链接 Problem Description " 改革春风吹满地, 不会AC没关系; 实在不行回老家, 还有一亩三分地. 谢谢!(乐队奏乐)" 话说部分学生心态极好,每天就知道 ...
- spring自定义参数绑定(日期格式转换)
spring参数绑定时可能出现 BindException(参数绑定异常),类似下面的日期绑定异常(前台传过来是String类型,实际的pojo是Date类型) default message [Fa ...
- jquery的ajax提交
ajax函数封装 function Ajax(imethod,iurl,iasync,idata,ifunc){ $.ajax({ type:imethod, cache: false, dataTy ...
- POJ1080(LCS变形)
Human Gene Functions Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Oth ...
- maven自动建立目录骨架
maven提供archetype插件,用于创建符合maven规定的目录骨架. 方式一: 命令行执行mvn archetype:generate,在回显中依次写入如下参数: 执行完成会自动的生成响应的标 ...
- C#实例:Unity依赖注入使用
http://jingyan.baidu.com/article/c74d6000840b260f6b595d78.html
- mysql管理和基本操作
进去mysql:mysql –uroot –p 重启数据库:[root@nanaLinux ~]# /etc/init.d/mysqld restart 1.Mysql忘记root密码 // 查看my ...