• 大数据学习——akka自定义RPC


    实现

    package cn.itcast.akka
    
    import akka.actor.{Actor, ActorSystem, Props}
    import akka.actor.Actor.Receive
    import com.typesafe.config.ConfigFactory
    
    import scala.collection.mutable
    
    import scala.concurrent.duration._
    
    class Master(val host: String, val port: Int) extends Actor {
    
      //保存WorkerID 到 WorkerInfo的映射
      val idToWorker = new mutable.HashMap[String, WorkerInfo]()
      //保存所的WorkerInfo信息
      val workers = new mutable.HashSet[WorkerInfo]()
    
      val CHECK_INTERVAL = 15000
    
      override def preStart(): Unit = {
        //导入隐式转换
        import context.dispatcher
        context.system.scheduler.schedule(0 millis, CHECK_INTERVAL millis, self, CheckTimeOutWorker)
      }
    
      override def receive: Receive = {
        //Worker发送个Mater的注册消息
        case RegisterWorker(workerId, cores, memory) => {
          if (!idToWorker.contains(workerId)) {
            //封装worker发送的信息
            val workerInfo = new WorkerInfo(workerId, cores, memory)
            //保存workerInfo
            idToWorker(workerId) = workerInfo
            workers += workerInfo
            //Master向Worker反馈注册成功的消息
            sender ! RegisteredWorker(s"akka.tcp://${Master.MASTER_SYSTEM}@$host:$port/user/${Master.MASTER_NAME}")
          }
        }
    
        //Worker发送给Master的心跳信息
        case Heartbeat(workerId) => {
          if (idToWorker.contains(workerId)) {
            val workerInfo = idToWorker(workerId)
            val currentTime = System.currentTimeMillis()
            //更新上一次心跳时间
            workerInfo.lastHeartbeatTime = currentTime
          }
        }
    
        //检测超时的Worker
        case CheckTimeOutWorker => {
          val currentTime = System.currentTimeMillis()
          val deadWorkers: mutable.HashSet[WorkerInfo] = workers.filter(w => currentTime - w.lastHeartbeatTime > CHECK_INTERVAL)
          //      for(w <- deadWorkers) {
          //        idToWorker -= w.id
          //        workers -= w
          //      }
          deadWorkers.foreach(w => {
            idToWorker -= w.id
            workers -= w
          })
          println("alive worker size : " + workers.size)
        }
      }
    }
    
    object Master {
    
      val MASTER_SYSTEM = "MaterActorSystem"
      val MASTER_NAME = "Master"
    
      def main(args: Array[String]) {
    
        //    val host = args(0)
        //    val port = args(1).toInt
        val host = "127.0.0.1"
        val port = 8888
        val confStr =
          s"""
             |akka.actor.provider = "akka.remote.RemoteActorRefProvider"
             |akka.remote.netty.tcp.hostname = "$host"
             |akka.remote.netty.tcp.port = "$port"
           """.stripMargin
        val conf = ConfigFactory.parseString(confStr)
        //ActorSystem是单例的,用于创建Acotor并监控actor
        val actorSystem = ActorSystem(MASTER_SYSTEM, conf)
        //通过ActorSystem创建Actor
        actorSystem.actorOf(Props(new Master(host, port)), MASTER_NAME)
        actorSystem.awaitTermination()
    
      }
    }
    package cn.itcast.akka
    
    trait Message extends Serializable
    
    //Worker -> Master
    case class RegisterWorker(id: String, cores: Int, memory: Int) extends Message
    
    //Master -> Worker
    case class RegisteredWorker(masterUrl: String) extends Message
    
    //Worker -> Master
    case class Heartbeat(id: String) extends Message
    
    //Worker internal message
    case object SendHeartbeat
    
    //Master internal message
    case object CheckTimeOutWorker
    package cn.itcast.akka
    
    import java.util.UUID
    import akka.actor.{Actor, ActorSelection, ActorSystem, Props}
    import com.typesafe.config.ConfigFactory
    
    import scala.concurrent.duration._
    
    class Worker(val cores: Int, val memory: Int, val masterHost: String, val masterPort: Int) extends Actor {
    
      //Master的引用
      var master: ActorSelection = _
      //Worker的ID
      val workerId = UUID.randomUUID().toString
      //masterUrl
      var masterUrl: String = _
    
      val HEARTBEAT_INTERVAL = 10000
    
      //preStart在构造器之后receive之前执行
      override def preStart(): Unit = {
        //首先跟Master建立连接
        master = context.actorSelection(s"akka.tcp://${Master.MASTER_SYSTEM}@$masterHost:$masterPort/user/${Master.MASTER_NAME}")
        //通过master的引用向Master发送注册消息
        master ! RegisterWorker(workerId, cores, memory)
      }
    
      override def receive: Receive = {
        //Master发送给Worker注册成功的消息
        case RegisteredWorker(masterUrl) => {
          this.masterUrl = masterUrl
          //启动定时任务,向Master发送心跳
          //导入隐式转换
          import context.dispatcher
          context.system.scheduler.schedule(0 millis, HEARTBEAT_INTERVAL millis, self, SendHeartbeat)
        }
    
        case SendHeartbeat => {
          //向Master发送心跳
          master ! Heartbeat(workerId)
        }
      }
    }
    
    object Worker {
      def main(args: Array[String]) {
    
        //Worker的地址和端口
        //    val host = args(0)
        //    val port = args(1).toInt
        //    val cores = args(2).toInt
        //    val memory = args(3).toInt
        val host = "127.0.0.1"
        val port = 9999
        val cores = 8
        val memory = 1024
    
        //Master的地址和端口
        //    val masterHost = args(4)
        //    val masterPort = args(5).toInt
        val masterHost = "127.0.0.1"
        val masterPort = 8888
    
        val confStr =
          s"""
             |akka.actor.provider = "akka.remote.RemoteActorRefProvider"
             |akka.remote.netty.tcp.hostname = "$host"
             |akka.remote.netty.tcp.port = "$port"
           """.stripMargin
        val conf = ConfigFactory.parseString(confStr)
        //单例的ActorSystem
        val actorSystem = ActorSystem("WorkerActorSystem", conf)
        //通过actorSystem来创建Actor
        val worker = actorSystem.actorOf(Props(new Worker(cores, memory, masterHost, masterPort)), "Worker")
        actorSystem.awaitTermination()
      }
    }
    package cn.itcast.akka
    
    
    class WorkerInfo(val id: String, val cores: Int, val memory: Int) {
    
      //TODO
      var lastHeartbeatTime: Long = _
    
    }

     

  • 相关阅读:
    如何实现Canvas图像的拖拽、点击等操作
    HTML5新增核心工具——canvas
    Java API 之 Object
    浅显回顾 Java 面向对象的最后方面的知识
    草叶集 | 在看惠特曼的大路之歌时的一些想法
    关于 static 和 final 的一些理解
    面向对象中的一些概念的理解
    关于前面知识的一些试题
    关于方法的一些浅见和对象的一些理解
    数组的一些应用场景
  • 原文地址:https://www.cnblogs.com/feifeicui/p/10996077.html
Copyright © 2020-2023  润新知