一、akka简介
Akka基于Actor模型,提供了一个用于构建可扩展的(Scalable)、弹性的(Resilient)、快速响应的(Responsive)应用程序的平台。
Actor模型:在计算机科学领域,Actor模型是一个并行计算(Concurrent Computation)模型,它把actor作为并行计算的基本元素来对待:为响应一个接收到的消息,一个actor能够自己做出一些决策,如创建更多的actor,或发送更多的消息,或者确定如何去响应接收到的下一个消息。
举例说明:
1.每名学生和每名老师都是Actor,是用来接收和发送消息,处理逻辑的;
2.老师的leader, 学生的leader, 是ActorSystem,用来创建Actor,并且监控和管理Actor;
3.ActorSystem是单例的,一个线程中只有一个即可
4.Actor是多例的,可以创建多个实例
5.Actor变成是通过消息传递实现并发的;
Actor是Akka中最核心的概念,它是一个封装了状态和行为的对象,Actor之间可以通过交换消息的方式进行通信,每个Actor都有自己的收件箱(Mailbox)。通过Actor能够简化锁及线程管理,可以非常容易地开发出正确地并发程序和并行系统,Actor具有如下特性:
1.提供了一种高级抽象,能够简化在并发(Concurrency)/并行(Parallelism)应用场景下的编程开发
2.提供了异步非阻塞的、高性能的事件驱动编程模型
3.超级轻量级事件处理(每GB堆内存几百万Actor)
二. Akka RPC程序
** 流程简图**
RPC代码实现
1 创建Master类 启动Master
1.1 指定配置(地址,端口等)
val confStr =
s"""
|akka.actor.provider = “akka.remote.RemoteActorRefProvider”
|akka.remote.netty.tcp.hostname = $masterHost
|akka.remote.netty.tcp.port = $masterPort
|""".stripMargin
1.2 解析配置
val configs: Config = ConfigFactory.parseString(confStr)
1.3创建ActorSystem对象
val actorSystem: ActorSystem = ActorSystem(MASTER_ACTOR_SYSTEM, config)
1.4创建Actor对象
val actor: ActorRef = actorSystem.actorOf(Props[MyMaster], "MASTER_ACTOR")
2.创建Worker类,启动worker
同Master类,区别在于创建ActorSystem对象时是 WORKER_ACTOR_SYSTEM.
3.master开启定时检查worker任务
Master继承Actor类,重写receive方法,重写preStart方法
开启定时任务,导入隐式转换,导入时间变量的包.
override def preStart(): Unit = {
//在preStart启动一个定时器,定期检测超时的Worker
import context.dispatcher
context.system.scheduler.schedule(0 millisecond,15000 millisecond,self,CheckTimeOutWoker)
}
4.worker和master建立连接并发送注册信息
Worker继承Actor类,重写receive 和 preStart方法;
建立连接,发送注册信息;
//在构造方法执行之后 ,receive执行之前,跟Master建立连接 并注册信息
override def preStart() = {
//Worker跟master 建立上了连接
masterRef= context.actorSelection(s"akka.tcp://${Master.MASTER_ACTOR_SYSTEM}@$masterHost:$masterPort/user/${Master.MASTER_ACTOR}")
//向master发送消息
masterRef ! RegisterWorker(workerId,memory,cores)
5.master接收worker注册信息
```scala
case RegisterWorker(id,memory,cores) =>{
//将Worker的信息保存起来
val workerInfo = new WorkerInfo(id, memory, cores)
//添加到map集合中
idToWorker(id)=workerInfo
//向Worker 返回一个注册成功的消息
sender() ! RegisteredWorker
}
6.worker接收master的注册成功信息,开启定时心跳反应
定时的心跳反应是向worker自己发送信息;worker在接收到信息之后再向master发出心跳反应
//Master向worker返回注册成功的消息
case RegisteredWorker =>{
//启动定时器 导入隐式转换
import context.dispatcher
context.system.scheduler.schedule(0 millisecond,10000 millisecond,self,SendHeartbeat)
}
//自己发送给自己的消息,定期的接收到该消息
case SendHeartbeat => {
//向 Master发送消息
masterRef ! Heartbeat(workerId)
}
7.master接收心跳信息,更新心跳时间
case Heartbeat(workerId) => {
if(idToWorker.contains(workerId)){
val workerInfo = idToWorker(workerId)
//更新对应的worker的时间
workerInfo.lastHeartbeatTime = System.currentTimeMillis()
}
8.master检查机制,移除未响应的worker
case CheckTimeOutWoker =>{
//获取当前时间
val currentTime = System.currentTimeMillis()
val deadWorkers = idToWorker.values.filter(w => currentTime - w.lastHeartbeatTime > 15000)
//移除超时的Worker
deadWorkers.foreach(w => {
//将超时的Worker移除
idToWorker -= w.id
})
println(s"current alive worker is : ${idToWorker.size}")
}