Akka框架
Akka是一个用 Scala 编写的库,用于简化编写容错的、高可伸缩性的 Java 和 Scala 的 Actor 模型应用。
Akka是JAVA虚拟机JVM平台上构建高并发、分布式和容错应用的工具包和运行时。
Akka处理并发的方法基于Actor模型。在Akka里,Actor之间通信的唯一机制就是消息传递。
比喻介绍: 多名学生与多名老师之间的问题咨询;
Actor编程模型
1.每名学生和每名老师都是Actor,是用来接收和发送消息,处理逻辑的;
2.老师的leader, 学生的leader, 是ActorSystem,用来创建Actor,并且监控和管理Actor;
3.ActorSystem是单例的,一个线程中只有一个即可
4.Actor是多例的,可以创建多个实例
5.Actor变成是通过消息传递实现并发的;
AkkaRpc项目流程简介
AkkaRpc项目编写步骤
1.创建Master类,启动master
1.1创建配置对象
val confStr: String =
s"""
|akka.actor.provider = "akka.remote.RemoteActorRefProvider"
|akka.remote.netty.tcp.hostname = ${masterHost}
|akka.remote.netty.tcp.port = ${masterPort}
|""".stripMargin
val config: Config = ConfigFactory.parseString(confStr)
1.2创建ActorSystem对象
val actorSystem: ActorSystem = ActorSystem(MASTER_ACTOR_SYSTEM, config)
1.3创建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 = {
import context.dispatcher
import scala.concurrent.duration._
context.system.scheduler.schedule(0 millisecond,15000 millisecond,self,CheckWorkers)
}
4.worker和master建立连接并发送注册信息
Worker继承Actor类,重写receive 和 preStart方法;
建立连接,发送注册信息;
override def preStart(): Unit = {
//MASTER的连接对象
coonMaster= context.actorSelection(s"akka.tcp://${Master.MASTER_ACTOR_SYSTEM}@$masterHost:$masterPort/user/${Master.MASTER_ACTOR}")
coonMaster ! MyWorkerRegister(workerId,memory,cores)
}
5.master接收worker注册信息
1.接收worker注册信息,并保存;
2.向worker发送注册成功信息;
override def receive: Receive = {
case MyWorkerRegister(workerId,memory,cores) =>{
val workerInfo = new WorkerInfo(workerId, memory, cores)
idToWorker(workerId) = workerInfo //保存信息
sender() ! Registered
}
6.worker接收master的注册成功信息,开启定时心跳反应
定时的心跳反应是向worker自己发送信息;worker在接收到信息之后再向master发出心跳反应
case Registered=>{
//开启定时任务.导入隐式转换
import context.dispatcher
import scala.concurrent.duration._
context.system.scheduler.schedule(0 millisecond,10000 millisecond,self,SendHeartBeat)
}
case SendHeartBeat => {
coonMaster ! HeatBeat(workerId)
}
7.master接收心跳信息,更新心跳时间
case HeatBeat(workId) =>{
if (idToWorker.contains(workId)){
val info: WorkerInfo = idToWorker(workId)
info.lastHeartBeat =System.currentTimeMillis()
}
}
8.master检查机制,移除未响应的worker
case CheckWorkers =>{
val currentTime: Long = System.currentTimeMillis()
val deadWorkers: Iterable[WorkerInfo] = idToWorker.values.filter(w => currentTime - w.lastHeartBeat > 15000)
deadWorkers.foreach(w => idToWorker-=w.workerId)
println(s"current alive worker is :${idToWorker.size}")
}