Scala——基于Akka的并发编程和分布式应用程序开发
来源:互联网 发布:东莞知美医院可靠吗 编辑:程序博客网 时间:2024/06/07 10:23
基于Akka分布式技术开发分布式应用程序,分为两个角色:
1、master
作用:接收worker的注册,并将worker的注册信息保存下来;感知worker的上下线;接收worker的汇报心跳,更新worker的相关信息;
定时检测超时的worker,并将超时的worker从集群中移除掉。
2、worker
1、master
作用:接收worker的注册,并将worker的注册信息保存下来;感知worker的上下线;接收worker的汇报心跳,更新worker的相关信息;
定时检测超时的worker,并将超时的worker从集群中移除掉。
2、worker
作用:向master进行注册,加入到集群中去;定时向master汇报心跳。
案例代码如下:
import akka.actor.Actor.Receiveimport akka.actor.{Actor, ActorSystem, Props}import com.typesafe.config.ConfigFactoryimport scala.collection.mutableimport scala.concurrent.duration._/** * Master.scala */class Master extends Actor { //worker ---->workInfo val idToWorker = new mutable.HashMap[String, WorkerInfo]() //WorkInfo val workers = new mutable.HashSet[WorkerInfo]() val checkTimeOutWorkerInterval = 5000 //preStart()是Master启动之后立即执行的方法 override def preStart(): Unit = { import context.dispatcher //启动一个定时器,定时检查超时的Worker context.system.scheduler.schedule(0 millis, checkTimeOutWorkerInterval millis, self, CheckTimeOutWorker) } override def receive: Receive = { case "started" => println("master startup successful...") //接收Worker发送过来的注册信息 case RegisterWorker(workerId, cores, memory) => { if (!idToWorker.contains(workerId)) { //3、将发送过来的Worker信息封装成WorkerInfo保存到HashMap和HashSet中 val workerInfo = new WorkerInfo(workerId, cores, memory) idToWorker.put(workerId, workerInfo) workers += workerInfo //4、master向worker发送注册成功的消息给worker //sender指代的是消息源,即谁发送过来的消息,就指代谁 sender() ! RegisteredWorker } } //Master接收Worker汇报的心跳信息 case SendHeartBeat(workerId) => { //从idToWorker中取出对应的Worker,并更新最近一次汇报心跳的时间 if (idToWorker.contains(workerId)) { val workerInfo = idToWorker(workerId) workerInfo.lastHeartBeatTime = System.currentTimeMillis() ///////////////////////////////////////// workers += workerInfo } } case CheckTimeOutWorker => { val currentTime = System.currentTimeMillis() //过滤出超时的Worker(即在指定的时间范围内没有向Master进行汇报) val toRemoves = workers.filter(w => currentTime - w.lastHeartBeatTime > checkTimeOutWorkerInterval) toRemoves.foreach(worker => { idToWorker.remove(worker.workerId) workers -= worker }) println(s"worker count is ${workers.size}") } }}object Master { def main(args: Array[String]): Unit = { val masterHost = "localhost" val masterPort = "8081" /** * 在实际应用场景下,有时候我们就是确实需要在scala创建多少字符串,但是每一行需要固定对齐。 * 解决该问题的方法就是应用scala的stripMargin方法,在scala中stripMargin默认是“|”作为出来连接符, * 在多行换行的行头前面加一个“|”符号即可。 * 当然stripMargin方法也可以自己指定“定界符”,同时更有趣的是利用stripMargin.replaceAll方法, * 还可以将多行字符串”合并”一行显示。 */ 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) //创建老大ActorSystem val masterActorSystem = ActorSystem("masterActorSystem", config) //使用ActorSystem创建actor val masterActor = masterActorSystem.actorOf(Props[Master], "masterActor") //给新创建的masterActor发送一条消息,发送消息使用感叹号"!" masterActor ! "started" //将ActorSystem阻塞在这,不要让其停止 masterActorSystem.whenTerminated }}
============================================================import java.util.UUIDimport akka.actor.Actor.Receiveimport akka.actor.{Actor, ActorSelection, ActorSystem, Props}import com.typesafe.config.ConfigFactoryimport scala.concurrent.duration._/** * Worker.scala */class Worker(var cores: Int, var memory: Int) extends Actor { var masterActor: ActorSelection = null var workerId = UUID.randomUUID().toString val heartBeatInterval = 3000 //actor启动后会立即执行此方法,只会执行一次 override def preStart(): Unit = { masterActor = context.actorSelection("akka.tcp://masterActorSystem@localhost:8081/user/masterActor") //2、worker启动后立即向master进行注册 masterActor ! RegisterWorker(workerId, cores, memory) } //用来接收消息的方法,这个方法会被多次执行,只要有消息过来就会被执行 override def receive: Receive = { case "started" => println("worker setup sucessful.....") //master发送过来的注册成功的消息 case RegisteredWorker => { //导入定时器 import context.dispatcher //开启定时任务 //此处的millis需要导入import scala.concurrent.duration._ context.system.scheduler.schedule(0 millis, heartBeatInterval millis, self, SendHeartBeat) } //向master汇报心跳 case SendHeartBeat => { masterActor ! SendHeartBeat(workerId) } }}object Worker { def main(args: Array[String]): Unit = { val workerHost = "localhost" val workerPort = "8084" /** * 在实际应用场景下,有时候我们就是确实需要在scala创建多少字符串,但是每一行需要固定对齐。 * 解决该问题的方法就是应用scala的stripMargin方法,在scala中stripMargin默认是“|”作为出来连接符, * 在多行换行的行头前面加一个“|”符号即可。 * 当然stripMargin方法也可以自己指定“定界符”,同时更有趣的是利用stripMargin.replaceAll方法, * 还可以将多行字符串”合并”一行显示。 */ 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) //创建老大ActorSystem val workerActorSystem = ActorSystem("workerActorSystem", config) //使用ActorSystem创建actor //创建一个Worker对象,Cores为62,memory为128 val workerActor = workerActorSystem.actorOf(Props(new Worker(62, 128)), "workerActor") //给新创建的masterActor发送一条消息,发送消息使用感叹号"!" workerActor ! "started" //将ActorSystem阻塞在这,不要让其停止 workerActorSystem.whenTerminated }}========================================================/** * WorkInfo.class * 用来封装Worker的基本信息 */class WorkerInfo(var workerId: String, var cores: Int, var memory: Int) { //worker最近汇报心跳的时间 var lastHeartBeatTime:Long = System.currentTimeMillis()}========================================================================/** * RemoteMessage.scala *///因为需要走网络,所以此trait需要继承Serializabletrait RemoteMessage extends Serializable {}//worker------>mastercase class RegisterWorker(var workerId: String, var cores: Int, var memory: Int) extends RemoteMessage//master ---->workercase class RegisteredWorker() extends RemoteMessage//worker ------> workerobject SendHeartBeat//worker------>mastercase class SendHeartBeat(var workerId: String)//master ------> masterobject CheckTimeOutWorker
阅读全文
0 0
- Scala——基于Akka的并发编程和分布式应用程序开发
- 第90讲:基于Scala的Actor之上的分布式并发消息驱动框架Akka初体验学习笔记
- 第90讲:基于Scala的Actor之上的分布式并发消息驱动框架Akka初体验
- Akka Scala编程实践,轻松开发多线程、分布式以及集群式程序
- scala分布式框架-akka
- AKKA 实现并发、分布式和容错
- 基于分布式计算模型AKKA的数据并发处理【Lync聊天记录 -www.msucplus.com】
- Scala和并发编程
- scala akka 修炼之路3(基于java nio的socket编程)
- scala akka基础编程
- Akka框架——第一节:并发编程简介
- Akka并发编程——1、Actor模型(一)
- Akka并发编程——2、Actor模型(二)
- Akka并发编程——3、Actor模型(三)
- Akka并发编程——4、Actor模型(四)
- Akka并发编程——5、Actor模型(五)
- Akka框架——第一节:并发编程简介
- AKKA并发编程简介
- Tarjan算法小结1——SCC
- Error: need a single repository as argument.(已解决)
- 20171103周测题
- Java编程思想第四版第三章练习
- oprofile性能分析优化程序
- Scala——基于Akka的并发编程和分布式应用程序开发
- MapReduce数据类型及自定义MapReduce数据类型
- physx 3.3.4中的 Revolute Joint
- 接口回调基础理解
- QVTKOpenGLWidget
- 路漫漫其修远兮,吾将上下而求索
- log4j过滤掉不必要的日志
- nginx1.12安装
- OpenStack deployed by SaltStack