RemoteMessage.scala

//对象要序列化才能通过网络传输   这个地方没有大括号....这有这个extends声明
trait RemoteMessage extends Serializable //Worker ->(发送给) Master Worker给Master节点发送注册消息
case class RegisterWorker(id:String, memory:Int, scores:Int ) extends RemoteMessage //接收已经在Master注册过的Worker定时发送来的心跳 Woker->Master
case class Heartbeat(id:String) extends RemoteMessage //Master -> Worker Master反馈给Worker已经注册的Worker有哪些
case class RegisteredWorker(masterUrl:String) extends RemoteMessage //Worker -> self //Worker先向自己发送一下心跳,这个地方可以做一下判断,根据实际情况,定义什么时候向Master发送消息
//在这个样例类中发送给Master的心跳 case class Heartbeat
case object SendHeartbeat //Master -> self Master自检查看Worker的状态
case object CheckTimeOutWorker

WorkerInfo.scala

class WorkerInfo(val id:String,val memory:Int,val scores:Int) {
//记录上一次心跳
var lastHeartbeatTime : Long = _
}

Worker.scala

import java.util.UUID
import com.typesafe.config.ConfigFactory
import akka.actor.Actor
import akka.actor.ActorSystem
import akka.actor.Props
import akka.actor.ActorSelection
import scala.concurrent.duration._ //如果不引入这个包 在 context.system.scheduler.schedule 中的mills 地方会报错 //使用Akka框架来实现RCP不同进程之间的方法调用 导入Actor是导入的akka包下的
//在Worker类上定义一个主构造器
class Worker (val masterHost:String ,val masterPort:Int ,val memory:Int ,val cores: Int) extends Actor {
var master : ActorSelection = _
//记录Worker从节点的id
val workerId = UUID.randomUUID().toString()
//记录Worker从节点的发送心跳的时间间隔
val HEART_INTERVAL = 10000 //preStart()方法在构造器之后,在receive之前执行 actorOf()方法执行 就会执行生命周期方法
override def preStart() : Unit={
//跟Master建立连接
master = context.actorSelection(s"akka.tcp://MasterSystem@$masterHost:$masterPort/user/Master")
//向Master发送注册消息
master ! RegisterWorker(workerId,memory,cores)
} override def receive: Receive = {
//Master对注册的Worker存储注册之后需要向Worker发送消息 来说明该Woker注册成功
//此处是Worker节点接收到Master节点的反馈消息
case RegisteredWorker(masterUrl) => {
println(masterUrl)
//启动定时器发送心跳
import context.dispatcher
//多长时间后执行 单位 ,多长时间执行一次 单位 ,消息的接受者(直接给master发不好,先给自己发送消息,以后可以做下判断,什么情况下再发送消息), 消息
context.system.scheduler.schedule(0 millis, HEART_INTERVAL millis, self, SendHeartbeat)
}
//Worker先向自己self发送一下心跳,这个地方可以做一下判断,根据实际情况,定义什么时候向Master发送消息
case SendHeartbeat =>{
println("send heartbeat to Master")
master ! Heartbeat(workerId)
}
}
}
object Worker{
def main(args: Array[String]): Unit = {
//从传入的参数列表中取得
val host = args(0)
val port = args(1).toInt
val masterHost = args(2)
val masterPort = args(3).toInt
val memory = args(4).toInt
val cores = args(5).toInt
//为了通过ActorSystem老大来获得Actor 准备配置
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)
//ActorSystem是所有Actor的老大,辅助创建和监控下面的Actor, 该老大是单例的.
//得到该老大的对象需要一个名字和配置对象config
val actorSystem = ActorSystem("WorkerSystem",config)
//actorOf方法执行,就会执行生命周期方法
actorSystem.actorOf(Props(new Worker(masterHost, masterPort, memory, cores)),"Worker")
actorSystem.awaitTermination()
}
}

Master.scala

import com.typesafe.config.ConfigFactory

import akka.actor.Actor
import akka.actor.ActorSystem
import akka.actor.Props
import scala.collection.mutable
import scala.concurrent.duration._ class Master(val host:String,val port:Int) extends Actor{ //定义一个HashMap用来存储注册Worker的信息
val idToWorkerHashMap = new mutable.HashMap[String,WorkerInfo]()
//定义一个HashSet用于存储 注册的Worker对象 WorkerInfo
val workersSet = new mutable.HashSet[WorkerInfo]() //使用set删除快, 也可用linkList
//超时检查的间隔 这个时间间隔一定要大于Worker向Master发送心跳的时间间隔.
val CHECK_INTERVAL = 15000 override def preStart() :Unit = {
println("preStart invoked")
//导入隐式转换
//使用timer太low了,可以使用akka的定时器,需要导入这个包
import context.dispatcher
context.system.scheduler.schedule(0 millis, CHECK_INTERVAL millis, self, CheckTimeOutWorker)
}
//接收Worker发送来的消息 可以有注册RegisterWorker 心跳Heartbeat
override def receive :Receive = {
case RegisterWorker(id,memory,cores) =>{
//判断该Worker是否已经注册过
if(!idToWorkerHashMap.contains(id)){
//把Worker的信息封装起来保存到内存中
val workerInfo = new WorkerInfo(id,memory,cores)
//以id为键 worker对象为值 添加到该idToWorker的HashMap对象中
idToWorkerHashMap(id) = workerInfo
//把workerInfo对象放到存储Woker的HashSet中
workersSet += workerInfo
//对注册的Worker存储注册之后需要向Worker发送消息 来说明该Woker注册成功
sender ! RegisteredWorker(s"akka.tcp://MasterSystem@$host:$port/user/Master")//通知worker注册
}
}
//接收已经在Master注册过的Worker定时发送来的心跳
case Heartbeat(id) =>{
if(idToWorkerHashMap.contains(id)){
val workerInfo = idToWorkerHashMap(id)
//报活 把该Worker给Master心跳的时间记录下来
val currentTime = System.currentTimeMillis()
workerInfo.lastHeartbeatTime = currentTime
}
}
//Master节点主动检测在Master自己这里注册Worker节点的存活状态
case CheckTimeOutWorker =>{
val currentTime = System.currentTimeMillis();
//如果当前时间和最近一次心跳时间的差值大于检测的时间间隔 就要干掉这个Worker
val toRemove = workersSet.filter(x => currentTime - x.lastHeartbeatTime > CHECK_INTERVAL)
for(w <- toRemove){
workersSet -= w
idToWorkerHashMap -= w.id
}
println(workersSet.size)
}
}
} object 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
//ConfigFactory 既有parseString 也有parseFile
val config = ConfigFactory.parseString(configStr)
//ActorSystem是所有Actor的老大,辅助创建和监控下面的所有Actor,它是单例的
val actorSystem = ActorSystem("MasterSystem",config)
val master = actorSystem.actorOf(Props(new Master(host,port)),"Master")
actorSystem.awaitTermination()
}
}

另外一个版本:http://www.cnblogs.com/DreamDrive/p/6736471.html

Scala使用Akka模拟RPC机制代码2的更多相关文章

  1. Scala使用Akka模拟RPC机制代码

    上代码:  另一个版本(自己加注释):http://www.cnblogs.com/DreamDrive/p/6740440.html RemoteMessage.scala trait Remote ...

  2. Hadoop学习笔记—3.Hadoop RPC机制的使用

    一.RPC基础概念 1.1 RPC的基础概念 RPC,即Remote Procdure Call,中文名:远程过程调用: (1)它允许一台计算机程序远程调用另外一台计算机的子程序,而不用去关心底层的网 ...

  3. Hadoop RPC机制的使用

    一.RPC基础概念 1.1 RPC的基础概念 RPC,即Remote Procdure Call,中文名:远程过程调用: (1)它允许一台计算机程序远程调用另外一台计算机的子程序,而不用去关心底层的网 ...

  4. 理解Android系统的进程间通信原理(二)----RPC机制

    理解Android系统中的轻量级解决方案RPC的原理,需要先回顾一下JAVA中的RMI(Remote Method Invocation)这个易于使用的纯JAVA方案(用来实现分布式应用).有关RMI ...

  5. 每天收获一点点------Hadoop RPC机制的使用

    一.RPC基础概念 1.1 RPC的基础概念 RPC,即Remote Procdure Call,中文名:远程过程调用: (1)它允许一台计算机程序远程调用另外一台计算机的子程序,而不用去关心底层的网 ...

  6. Hadoop的RPC机制及简单实现

    1.RPC简介 Remote Procedure Call 远程过程调用协议 RPC——远程过程调用协议,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议.RPC协议假定某些 ...

  7. Hadoop2源码分析-RPC机制初识

    1.概述 上一篇博客,讲述Hadoop V2的序列化机制,这为我们学习Hadoop V2的RPC机制奠定了基础.RPC的内容涵盖的信息有点多,包含Hadoop的序列化机制,RPC,代理,NIO等.若对 ...

  8. hadoop的RPC机制 -源码分析

    这些天一直奔波于长沙和武汉之间,忙着腾讯的笔试.面试,以至于对hadoop RPC(Remote Procedure Call Protocol ,远程过程调用协议,它是一种通过网络从远程计算机程序上 ...

  9. Hadoop中的RPC机制

    1.  RPC——远程过程调用协议,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议.RPC协议假定某些传输协议的存在,如TCP或UDP,为通信程序之间携带信息数据.在OSI ...

随机推荐

  1. CentOS7安装MySQL并设置远程登陆

    1 下载并安装MySQL官方的 Yum Repository [root@localhost ~]# wget -i -c http://dev.mysql.com/get/mysql57-commu ...

  2. php代码记录

    公司项目的随想记录也记在这里: 1,证书产生的目的是为了防止不合法的用户能够直接访问接口获取数据.证书由服务器端生成,然后返回给app.然后app拿着这个证书到服务器端获取接口数据,而不是app的合法 ...

  3. DOS的几个常用命令

    1.rem:注释 DOS中的注释,其后面的内容会被自动忽略.双冒号(::)也有相同的效果 相当于R语言和Python中的# 2.set:设置变量 set var = 1 将1赋值给变量var 打印出来 ...

  4. JavaBase

    第一章: Java之父:詹姆斯.高斯林:1995年5月推出Java: java分为  java se : 基础版本(标准版) Java  EE  : 企业级开发   ME:嵌入式开发(已被安卓替代) ...

  5. C#-VS程序集

    程序集即代码组,可以是单个文件或多个文件,按一个整体部署,但可指定自身调用其他程序集的版本. 推出原因 为解决dll地狱而推出,也可解决其他问题.dll地狱,a应用使用dll版本1,b应用使用dll版 ...

  6. Jmeter-接口功能测试

    前言 前面已经讲过了如何用Postman做接口功能测试,本篇主要是用Jmeter来演示如何做接口功能测试,这里就大致说一下Jmeter如何用哈,其余的也不多说了. Jmeter接口功能测试实例 因为在 ...

  7. 关于自定义脚本rc.local里开机不启动的问题--以tomcat和perl相关的脚本为例

    本文将自己遇到的一些自定义脚本加入开机启动项却不成功的问题加以说明,花费了我很长时间才得以解决,当然也多谢了自己朋友的帮忙,正是因为他们的提醒,最后才找到了解决的办法,谢谢他们!!!! 系统是cent ...

  8. Alpha冲刺 - (3/10)

    Part.1 开篇 队名:彳艮彳亍团队 组长博客:戳我进入 作业博客:班级博客本次作业的链接 Part.2 成员汇报 组员1(组长)柯奇豪 过去两天完成了哪些任务 ssm框架的使用并实现简单的数据处理 ...

  9. 入手IntelliJ IDEA 常用配置

    Idea常用设置 下载地址:https://www.jetbrains.com/idea/ 激活服务器:http://idea.iteblog.com/key.php 代码补全取消区分大小写 Inte ...

  10. Python3 安装 PyQt5 -pycharm 环境搭建

    执行命令: pip3 install PyQt5 PyQt5+python3+pycharm开发环境配置   1.下载PyQt 官方网站:http://www.riverbankcomputing.c ...