利用scala实现YARN的RPC

3 篇文章 0 订阅
1 篇文章 0 订阅

根据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)
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值