根据scala实现YARN的RPC功能
YARN主要分为ResourceManager和DataManager
ResourceManager主要负责接收DataManager的请求,例如注册,资源调度等
DataManager每隔一段时间会进行心跳信息的反馈给RM,RM判断DataManager是否还在线
实现思路:
一.首先创建两个object
1 MyNodeManager
2 MyResourceManager
并且创建对应的伴生类
二.创建对应的ActorSystem管理和创建Actor
三.利用样例类作为消息传递的对象
四.先启动ResourceManager,查看地址
五.NodeManager的preStart方法连接ResourceManager的地址,并发送注册请求
六.RM返回注册成功消息后,NM开始进行心跳反馈
七.RM创建一个Map存放最新的心跳信息(主机名,最新心跳时间戳)
七.RM在preStart就进行checkHB方法,查看各节点最新的时间戳,和现在的时间作对比,如果时间大于5000ms,就把该节点从Map中移除
以下是代码的实现
Message
case class Register(host:String,memory:String,cpu:String)//注册消息 case class sendBackRS(mes:String)//服务器端返回注册成功的信息 case class sendBackHB(mes:String)//服务器端返回的心跳 case class HeartBeat(hostName:String)//主机名,心跳信息 case class checkHB()
MyResourceManager
import akka.actor.{Actor, ActorSystem, Props} import com.typesafe.config.{Config, ConfigFactory} import scala.collection.mutable.Map import scala.concurrent.duration._ object MyResourceManager { var hostmap:Map[String,String]=Map() def main(args: Array[String]): Unit = { val str= """ |akka.actor.provider = "akka.remote.RemoteActorRefProvider" |akka.remote.netty.tcp.hostname =localhost |akka.remote.netty.tcp.port=19888 """.stripMargin val conf: Config = ConfigFactory.parseString(str) // def apply(name: String, config: Config) val actorSystem = ActorSystem("MyResourceManagerActorSystem",conf) //创建并启动actor def actorOf(props: Props, name: String): ActorRef //new MyResourceManager() 会导致主构造函数会运行!! actorSystem.actorOf(Props(new MyResourceManager()),"MyResourceManagerActor") //akka.tcp://MyResourceManagerActorSystem@localhost:19888 } } class MyResourceManager extends Actor{ override def receive:Receive = { case Register(host,memory,cpu)=>{ doRegister(host,memory,cpu)//调用注册方法 println(s"已接收到注册信息 主机:$host 内存:$memory cpu:$cpu") sender() ! sendBackRS("注册成功") } case HeartBeat(x)=>{ var y=System.currentTimeMillis() println(s"心跳反馈 主机:$x 时间$y") //创建一个map记录 //定时器返回sendBackHB("心跳正常") MyResourceManager.hostmap+=(x->y.toString) } case checkHB()=>{ var nowTime=System.currentTimeMillis() for(nm<-MyResourceManager.hostmap){ var lastTime=nm._2.toLong if(nowTime-lastTime>5000 ){ println(s"主机${nm._1}已挂") MyResourceManager.hostmap.remove(nm._1.toString) } } } } override def preStart(): Unit = { import scala.concurrent.duration._ import context.dispatcher context.system.scheduler.schedule(0 millis,5000 millis,self,checkHB()) } def doRegister(host:String,memory:String,cpu:String):Map[String,String]={//注意 返回的Map要声明泛型 val reMap=Map("host"->host,"memory"->memory,"cpu"->cpu) reMap } }
MyNodeManager
import akka.actor.{Actor, ActorRef, ActorSystem, Props} import com.typesafe.config.ConfigFactory import scala.concurrent.duration._ object MyNodeManager { var NMactor:ActorRef=_ var time=System.currentTimeMillis() var hostname:String =_ var port:Int =_ def main(args: Array[String]): Unit = { hostname=args(0) port=args(1).toInt val str= s""" |akka.actor.provider = "akka.remote.RemoteActorRefProvider" |akka.remote.netty.tcp.hostname = localhost |akka.remote.netty.tcp.port = ${port} """.stripMargin val conf = ConfigFactory.parseString(str) val actorySystem = ActorSystem("MyNodeManagerActorySystem",conf) NMactor= actorySystem.actorOf(Props(new MyNodeManager()),"MyNodeManagerActory") } } class MyNodeManager extends Actor{ override def receive: Receive = { case sendBackRS("注册成功")=>{ //开启定时器调用心跳机制 println("我注册成功了") sender() ! HeartBeat(MyNodeManager.hostname) autoHearBeat(sender()) } case sendBackHB("心跳正常11")=>{ autoHearBeat(sender()) } } override def preStart(): Unit = { var rmref=context.actorSelection("akka.tcp://MyResourceManagerActorSystem@localhost:19888/user/MyResourceManagerActor") //获取主机名 ,cpu 内存 rmref ! Register(MyNodeManager.hostname,MyNodeManager.port.toString,"26HZ") //C:/Winnt/System32/Drivers/Etc这个文件存放了ip地址 /*var ac=rmref.anchor autoHearBeat()*/ //autoHearBeat() } def autoHearBeat(ac:ActorRef):Unit={ import context.dispatcher context.system.scheduler.schedule(0 milliseconds, 3 seconds,ac, creatHB(MyNodeManager.hostname)) println("定时发送") } //import context.dispatcher //context.system.scheduler.schedule(0 seconds, 15 seconds, , sendBackHB("心跳接收完毕")) /*1、在第一次运行的时候需要等待多少时间; 2、子序列循序的频率; 3、我们想发送消息的目标ActorRef ; 4、消息*/ def creatHB(host:String):HeartBeat={ var hostname=host HeartBeat(host) } }