Scala-AKKA基础代码实现

AKKA底层实现原理

代码实现

import akka.actor.{Actor, ActorSystem, Props}
import com.typesafe.config.ConfigFactory

import scala.collection.mutable
import scala.concurrent.duration._


class Master extends Actor{
  //将Worker信息存到map集合中
  val map = new mutable.HashMap[String, WorkerInfo]()


  override def preStart(): Unit = {
    import context.dispatcher
    context.system.scheduler.schedule(0.millisecond,15000.millisecond,self,CheckTimeOutWorker)
  }

  //消息的接受  此函数为偏函数 不需要写match
  override def receive: Receive = {
    //做模式匹配
    case "hello" =>{
      println("hello")
    }

    case CheckTimeOutWorker =>{
      val deadWorker: Iterable[WorkerInfo] = map.values.filter(x => System.currentTimeMillis() - x.lastHeartbeatTime > 15000)

      deadWorker.foreach(m =>{
        map -= m.workerId
      })
      println(s"current alive worker size: ${map.size}")
    }

      //匹配worker发送来的注册信息
    case Conf(workerId, memory, cores) => {
//      println(s"workerId:$workerId,memory:$memory,cores:$cores")
      //将Worker的数据存到内存中
      val workInfo = new WorkerInfo(workerId, memory, cores)
      map(workerId) = workInfo
      //返回一个注册成功的响应
      sender() ! Confed
    }


      //接受Worker的心跳 并更新心跳时间
    case HeartBeat(workerId) =>   {
      //根据workerId查找对应的Worker信息
      if (map.contains(workerId)){
        val workerInfo: WorkerInfo = map(workerId)
        //更新Worker心跳的时间 更新到当前时间
        workerInfo.lastHeartbeatTime = System.currentTimeMillis()
      }
    }

  }
}
object Master{
  def main(args: Array[String]): Unit = {

    val host = "localhost"
    val port = 8888

    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)
    //创建MasterActorSystem(单例)
    val masterActorSystem = ActorSystem("MasterActorSystem", config)

    //通过Master创建Actor
    val masterActor = masterActorSystem.actorOf(Props[Master], "MasterActor")

    //自己给自己发消息
    masterActor ! "hello"

  }
}
import java.util.UUID

import akka.actor.{Actor, ActorSelection, ActorSystem, Props}
import com.typesafe.config.ConfigFactory

import scala.concurrent.duration._

class Worker extends Actor{

  var workerId = UUID.randomUUID().toString

  var selection: ActorSelection = _


  //是在构造方法之后,receive方法之前一定会调用一次
  override def preStart(): Unit = {
    //与master建立连接
    selection = context.actorSelection("akka.tcp://MasterActorSystem@localhost:8888/user/MasterActor")
    //向master注册信息
    selection ! Conf(workerId, 2040, 4)
  }


  //消息的接受  此函数为偏函数 不需要写match
  override def receive: Receive = {
    //做模式匹配
    case "hello" =>{
      println("hello")
    }

      //向Master发送一个心跳
    case SendHeartBeat =>{
      selection ! HeartBeat(workerId)
    }


    //启动定时器
    case Confed  =>{
      //导包 隐式转换
      import context.dispatcher
      context.system.scheduler.schedule(0.millisecond,10000.millisecond,self,SendHeartBeat)
    }

  }
}

object Worker{
  def main(args: Array[String]): Unit = {

    val host = "localhost"
    val port = 9999

    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)
    //创建WorkerActorSystem
    val workerActorSystem = ActorSystem("WorkerActorSysytem", config)
    //通过WorkActorSystem创建WorkerActor
    workerActorSystem.actorOf(Props[Worker], "WorkerActor")
  }
}
case class Conf(workerId: String, memory: Int, cores: Int)
case object Confed
case class WorkerInfo(workerId: String, memory: Int, cores: Int){

  var lastHeartbeatTime:Long = _
}
case object SendHeartBeat
case class HeartBeat(workerId: String)
case object CheckTimeOutWorker

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值