master
package com.doit.demo02
import akka.actor.{Actor, ActorSystem, Props}
import com.typesafe.config.ConfigFactory
import scala.collection.mutable
import scala.concurrent.duration._
class Master extends Actor{
val idToWorkerMap = new mutable.HashMap[String,WorkerInfo]()
override def preStart(): Unit = {
import context.dispatcher
context.system.scheduler.schedule(0.milliseconds , 15000.milliseconds , self ,CheckTimeOutWorker )
}
override def receive: Receive = {
case RegisterWorker(workerId,memory,cores) => {
val workerInfo = new WorkerInfo(workerId, memory, cores)
if (!idToWorkerMap.contains(workerId)) {
idToWorkerMap.put(workerId,workerInfo)
}
sender() ! RegisteredWorker
}
case HearBeat(workerId) => {
val workerInfo: WorkerInfo = idToWorkerMap(workerId)
val currenTime: Long = System.currentTimeMillis()
workerInfo.lastHearBeatTime = currenTime
}
case CheckTimeOutWorker =>{
val deadWorkers: Iterable[WorkerInfo] = idToWorkerMap.values.filter(w => System.currentTimeMillis() - w.lastHearBeatTime > 10000)
deadWorkers.foreach(w =>{
idToWorkerMap.remove(w.workerId)
})
println(s"current alive worker size is ${idToWorkerMap.size}")
}
}
}
object Master{
val MASTER_ACTOR_SYSTEM = "MASTER_ACTOR_SYSTEM"
val MASTER_ACTOR = "MASTER_ACTOR"
def main(args: Array[String]): Unit = {
val masterHost = "localhost"
val masterPort = 8888
val configStr = s"""
|akka.actor.provider = "akka.remote.RemoteActorRefProvider"
|akka.remote.netty.tcp.hostname = $masterHost
|akka.remote.netty.tcp.port = $masterPort
|""".stripMargin
val config = ConfigFactory.parseString(configStr)
val system: ActorSystem = ActorSystem(MASTER_ACTOR_SYSTEM , config)
system.actorOf(Props[Master] , MASTER_ACTOR)
}
}
woker
package com.doit.demo02
import java.util.UUID
import akka.actor.{Actor, ActorSelection, ActorSystem, Props}
import com.typesafe.config.{Config, ConfigFactory}
import scala.concurrent.duration._
class Worker(val masterHost:String , val masterPort:Int , var workerMemory:Int , var workerCores:Int) extends Actor{
val workerId = UUID.randomUUID().toString
var masterRef: ActorSelection = null
override def preStart(): Unit = {
masterRef = context.actorSelection(s"akka.tcp://${Master.MASTER_ACTOR_SYSTEM}@$masterHost:$masterPort/user/${Master.MASTER_ACTOR}")
masterRef ! RegisterWorker(workerId , workerMemory ,workerCores)
}
override def receive: Receive = {
case RegisteredWorker =>{
import context.dispatcher
context.system.scheduler.schedule(0.milliseconds , 10000.milliseconds , self , SendHearBeat)
}
case SendHearBeat =>{
masterRef ! HearBeat(workerId)
}
}
}
object Worker{
val WORKER_ACTOR_SYSTEM = "WORKER_ACTOR_SYSTEM"
val WORKER_ACTOR = "WORKER_ACTOR"
def main(args: Array[String]): Unit = {
val masterHost = "localhost"
val masterPort = 8888
val workerHost = "localhost"
val workerPort = 9999
val workerMemory = 4086
val workerCores = 8
val configStr =
s"""
|akka.actor.provider = "akka.remote.RemoteActorRefProvider"
|akka.remote.netty.tcp.hostname = $workerHost
|akka.remote.netty.tcp.port = $workerPort
|""".stripMargin
val config: Config = ConfigFactory.parseString(configStr)
val system: ActorSystem = ActorSystem(WORKER_ACTOR_SYSTEM , config)
system.actorOf(Props(new Worker(masterHost , masterPort , workerMemory ,workerCores)) , WORKER_ACTOR)
}
}
workerInfo
package com.doit.demo02
class WorkerInfo(val workerId:String , var memory:Int , var cores:Int) {
var lastHearBeatTime:Long = _
}
Messages
package com.doit.demo02
case object CheckTimeOutWorker
case class RegisterWorker(workerId:String , memory:Int , cores:Int)
case object RegisteredWorker
case class HearBeat(workerId:String)
case object SendHearBeat