需求如下图:
Master代码:
package com.season.rpc.akka
import akka.actor.{Actor, ActorSystem, Props}
import com.typesafe.config.ConfigFactory
import scala.collection.mutable
import scala.concurrent.duration._
/**
* Created by Administrator on 2017/5/2 0002.
*/
class Master extends Actor {
val CHECK_INTERVAL = 15000
val id2Worker = new mutable.HashMap[String,WorkerInfo]{}
val workers = new mutable.HashSet[WorkerInfo]()
override def preStart(): Unit = {
//启动一个定时器
import context.dispatcher
context.system.scheduler.schedule(0 millis,CHECK_INTERVAL millis,self,CheckTimeOutWorker)
}
override def receive: Receive = {
case RegisterWorker(workerId,memory,cores) => {
println(s"a connection from worker workerId : $workerId ram: $memory cpu: $cores")
val workerInfo = new WorkerInfo(workerId,memory,cores)
id2Worker(workerId) = workerInfo
workers += workerInfo
sender ! RegisteredWorker
}
case HeartBeat(workerId) => {
println(s"a heartbeat from worker workerId : $workerId")
val workerInfo: WorkerInfo = id2Worker(workerId)
val current = System.currentTimeMillis()
workerInfo.lastHeartbeatTime = current
}
case CheckTimeOutWorker => {
println("internal msg check")
val current = System.currentTimeMillis()
//过滤掉超时的workers
val deadWorkers = workers.filter(w => current - w.lastHeartbeatTime > CHECK_INTERVAL)
// for (workerInfo <- deadWorkers){
// id2Worker -= workerInfo.id
// workers -= workerInfo
// }
deadWorkers.foreach(workerInfo => {
id2Worker -= workerInfo.id
workers -= workerInfo
})
println(id2Worker.size)
}
}
}
object Master {
val MASTER_ACTOR_SYSTEM = "MasterSystem"
val MASTER_ACTOR_NAME = "Master"
def main(args: Array[String]): Unit = {
val host = args(0)
val port = args(1).toInt
val configStr =
s"""
|akka.actor.provider = "akka.remote.RemoteActorRefProvider"
|akka.remote.netty.tcp.hostname = "$host"
|akka.remote.netty.tcp.port = "$port"
""".stripMargin
val config = ConfigFactory.parseString(configStr)
val actorSystem = ActorSystem(MASTER_ACTOR_SYSTEM, config)
val masterActor = actorSystem.actorOf(Props[Master], MASTER_ACTOR_NAME)
//masterActor ! "CheckTimeout"
}
}
Worker代码:
package com.season.rpc.akka
import java.util.UUID
import akka.actor.{Actor, ActorSelection, ActorSystem, Props}
import com.typesafe.config.ConfigFactory
import scala.concurrent.duration._
/**
* Created by Administrator on 2017/5/2 0002.
*/
class Worker(val host: String ,val port: Int ,val memory: Int ,val cores: Int) extends Actor{
val WORKER_ID = UUID.randomUUID().toString
val HEARTBEAT_INTERVAL = 10000
var masterRef : ActorSelection =_
override def preStart(): Unit = {
masterRef = context.actorSelection(s"akka.tcp://${Master.MASTER_ACTOR_SYSTEM}@$host:$port/user/${Master.MASTER_ACTOR_NAME}")
masterRef ! RegisterWorker(WORKER_ID,memory,cores)
}
override def receive: Receive = {
case RegisteredWorker => {
import context.dispatcher
context.system.scheduler.schedule(0 millis,HEARTBEAT_INTERVAL millis,self,SendHearBeat)
}
case SendHearBeat => {
masterRef ! HeartBeat(WORKER_ID)
}
}
}
object Worker {
val WORKER_ACTOR_SYSTEM = "WorkerSystem"
val WORKER_ACTOR_NAME = "Worker"
def main(args: Array[String]): Unit = {
val workerHost = args(0)
val workerPort = args(1).toInt
val masterHost = args(2)
val masterPort = args(3).toInt
val workerMemory = args(4).toInt
val workerCores = args(5).toInt
val configStr =
s"""
|akka.actor.provider = "akka.remote.RemoteActorRefProvider"
|akka.remote.netty.tcp.hostname = "$workerHost"
|akka.remote.netty.tcp.port = "$workerPort"
""".stripMargin
val config = ConfigFactory.parseString(configStr)
val actorSystem = ActorSystem(WORKER_ACTOR_SYSTEM, config)
actorSystem.actorOf(Props(new Worker(masterHost,masterPort,workerMemory,workerCores)),WORKER_ACTOR_NAME)
}
}
workinfo.scala
package com.season.rpc.akka
/**
* Created by Administrator on 2017/5/2 0002.
*/
class WorkerInfo(val id : String , val memory : Int , val cores : Int) {
var lastHeartbeatTime: Long = 0
}
信息类:
package com.season.rpc.akka
/**
* Created by Administrator on 2017/5/2 0002.
*/
case class RegisterWorker(workerId: String , memory: Int ,cores: Int) extends Serializable
case class RegisteredWorker() extends Serializable
case class HeartBeat(workerId : String) extends Serializable
case object CheckTimeOutWorker
case object SendHearBeat