思路分析

1.首先启动master,然后依次启动worker

2.启动worker时,向master发送注册信息(使用case class封装注册信息——workerID,memory,cores)

3.接收注册信息,保存注册的worker信息,返回注册成功的消息

4.worker需要定时向master发送心跳信息,这么做的目的是报活

5.master需要定时进行心跳超时检测,剔除心跳超时的worker


步骤

一、创建maven工程,导包

  1. <properties>
  2. <maven.compiler.source>1.8</maven.compiler.source>
  3. <maven.compiler.target>1.8</maven.compiler.target>
  4. <encoding>UTF-8</encoding>
  5. <scala.version>2.11.8</scala.version>
  6. <scala.compat.version>2.11</scala.compat.version>
  7. </properties>
  8. <dependencies>
  9. <dependency>
  10. <groupId>org.scala-lang</groupId>
  11. <artifactId>scala-library</artifactId>
  12. <version>${scala.version}</version>
  13. </dependency>
  14. <dependency>
  15. <groupId>com.typesafe.akka</groupId>
  16. <artifactId>akka-actor_2.11</artifactId>
  17. <version>2.3.14</version>
  18. </dependency>
  19. <dependency>
  20. <groupId>com.typesafe.akka</groupId>
  21. <artifactId>akka-remote_2.11</artifactId>
  22. <version>2.3.14</version>
  23. </dependency>
  24. </dependencies>
  25. <build>
  26. <sourceDirectory>src/main/scala</sourceDirectory>
  27. <testSourceDirectory>src/test/scala</testSourceDirectory>
  28. <plugins>
  29. <!-- 限制jdk的编译版本插件 -->
  30. <plugin>
  31. <groupId>org.apache.maven.plugins</groupId>
  32. <artifactId>maven-compiler-plugin</artifactId>
  33. <version>3.0</version>
  34. <configuration>
  35. <source>1.8</source>
  36. <target>1.8</target>
  37. <encoding>UTF-8</encoding>
  38. </configuration>
  39. </plugin>
  40. <plugin>
  41. <groupId>net.alchim31.maven</groupId>
  42. <artifactId>scala-maven-plugin</artifactId>
  43. <version>3.2.2</version>
  44. <executions>
  45. <execution>
  46. <goals>
  47. <goal>compile</goal>
  48. <goal>testCompile</goal>
  49. </goals>
  50. <configuration>
  51. <args>
  52. <arg>-dependencyfile</arg>
  53. <arg>${project.build.directory}/.scala_dependencies</arg>
  54. </args>
  55. </configuration>
  56. </execution>
  57. </executions>
  58. </plugin>
  59. <plugin>
  60. <groupId>org.apache.maven.plugins</groupId>
  61. <artifactId>maven-shade-plugin</artifactId>
  62. <version>2.4.3</version>
  63. <executions>
  64. <execution>
  65. <phase>package</phase>
  66. <goals>
  67. <goal>shade</goal>
  68. </goals>
  69. <configuration>
  70. <filters>
  71. <filter>
  72. <artifact>*:*</artifact>
  73. <excludes>
  74. <exclude>META-INF/*.SF</exclude>
  75. <exclude>META-INF/*.DSA</exclude>
  76. <exclude>META-INF/*.RSA</exclude>
  77. </excludes>
  78. </filter>
  79. </filters>
  80. <transformers>
  81. <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
  82. <resource>reference.conf</resource>
  83. </transformer>
  84. <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
  85. <mainClass></mainClass>
  86. </transformer>
  87. </transformers>
  88. </configuration>
  89. </execution>
  90. </executions>
  91. </plugin>
  92. </plugins>
  93. </build>

二、master进程代码开发

  1. import akka.actor.{Actor, ActorRef, ActorSystem, Props}
  2. import com.typesafe.config.{Config, ConfigFactory}
  3. import scala.collection.mutable
  4. import scala.collection.mutable.ArrayBuffer
  5. import scala.concurrent.duration._
  6. //todo 利用akka实现spark通信---master端
  7. class Master extends Actor {
  8. //定义数据结构map 保存worker注册信息 k:workerId v:workerInfo
  9. private val workerInfoMap = new mutable.HashMap[String, WorkerInfo]()
  10. //定义数据结构保存worker信息,便于后续业务根据worker资源排序 (可选项)
  11. private val workerInfoArray = new ArrayBuffer[WorkerInfo]()
  12. override def preStart(): Unit = {
  13. //在初始化中完成首次心跳超时检查,后续间隔指定的时间检查
  14. //todo 记得导包
  15. import context.dispatcher
  16. context.system.scheduler.schedule(0 millis,12000 millis,self,CheckTimeOut)
  17. }
  18. //用receive方法持续不断接收处理akka actor的消息
  19. override def receive: Receive = {
  20. //用于接收注册信息
  21. case RegisterMessage(workerId,memory,cores) => {
  22. //判断worker是否注册
  23. if (!workerInfoMap.contains(workerId)){
  24. //如果未注册
  25. val workerInfo = new WorkerInfo(workerId, memory, cores)
  26. workerInfoMap.put(workerId,workerInfo)
  27. workerInfoArray += workerInfo
  28. //注册成功 返回注册成功信息
  29. sender ! RegisterSuccess(s"$workerId,congratulations!You successfully login!")
  30. }
  31. }
  32. //用于接收worker心跳信息
  33. case HeartBeatMessage(workerId) =>{
  34. //判断workerId是否注册,如果注册 更新上次心跳时间
  35. if (workerInfoMap.contains(workerId)){
  36. //把当前系统的时间更新为worker上次心跳的时间
  37. val nowTime: Long = System.currentTimeMillis()
  38. val info: WorkerInfo = workerInfoMap(workerId)
  39. info.lastHeartBeatTime = nowTime
  40. }
  41. }
  42. //用于心跳超时检查
  43. case CheckTimeOut =>
  44. //如何判断心跳超时?
  45. //当前时间 - 上次心跳时间(10s) > 10 如果没有网络波动应该是这样
  46. //如果要考虑网络波动,则可以 当前时间 - 上次心跳时间(10s) > 10
  47. val outTimeWorker: ArrayBuffer[WorkerInfo] = workerInfoArray.filter(x => System.currentTimeMillis() - x.lastHeartBeatTime > 12000)
  48. //遍历超时worker并剔除
  49. for (w <- outTimeWorker){
  50. val workerId = w.workerId
  51. workerInfoMap.remove(workerId)
  52. workerInfoArray -= w
  53. //打印超时的workId
  54. println(s"$workerId 已超时")
  55. }
  56. //打印当前存活的workerId数
  57. println(s"当前存活的worker个数是 ${workerInfoArray.size}")
  58. //worker排序
  59. println(workerInfoArray.sortBy(x => x.memory).reverse)
  60. }
  61. }
  62. object Master {
  63. def main(args: Array[String]): Unit = {
  64. //master host
  65. val host = args(0)
  66. //master port
  67. val port = args(1)
  68. //创建config需要解析的字符串
  69. val configStr: String =
  70. s"""
  71. |akka.actor.provider = "akka.remote.RemoteActorRefProvider"
  72. |akka.remote.netty.tcp.hostname = "$host"
  73. |akka.remote.netty.tcp.port = "$port"
  74. |""".stripMargin
  75. //创建ActorSystem需要的config
  76. val config: Config = ConfigFactory.parseString(configStr)
  77. //创建ActorSystem
  78. val masterActorSystem: ActorSystem = ActorSystem.create("masterActorSystem", config)
  79. //创建masterActor
  80. val master: ActorRef = masterActorSystem.actorOf(Props(new Master), "masterActor")
  81. }
  82. }

三、worker进程代码开发

  1. import java.util.UUID
  2. import akka.actor.{Actor, ActorRef, ActorSelection, ActorSystem, Props}
  3. import com.typesafe.config.{Config, ConfigFactory}
  4. import scala.concurrent.duration._
  5. //todo 利用akka实现spark通信---worker端
  6. class Worker(memory: Int,cores: Int) extends Actor {
  7. var master: ActorSelection = _
  8. //workerID
  9. val workerId = UUID.randomUUID().toString
  10. override def preStart(): Unit = {
  11. //引用master (协议、masterActorSystem、ip、端口号、actorMaster、actor层级)
  12. master = context.actorSelection("akka.tcp://masterActorSystem@192.168.0.108:12323/user/masterActor")
  13. //给master发送注册信息 使用case class封装
  14. master ! RegisterMessage(workerId,memory,cores)
  15. }
  16. override def receive: Receive = {
  17. //接收master返回的注册成功信息
  18. case RegisterSuccess(msg) => {
  19. println(msg)
  20. //注册成功,立即开始首次心跳,以后间隔指定的时间进行心跳
  21. //需要四个参数,心跳开始时间、心跳间隔时间、发给谁、发送信息
  22. //定时的消息只能发送给自己
  23. //todo 记得导包
  24. import context.dispatcher
  25. context.system.scheduler.schedule(0 millis,10000 millis,self,HeartBeat)
  26. }
  27. //接收心跳提醒,完成真正的心跳动作
  28. case HeartBeat => {
  29. master ! HeartBeatMessage(workerId)
  30. }
  31. }
  32. }
  33. object Worker{
  34. def main(args: Array[String]): Unit = {
  35. //worker host
  36. val host = args(0)
  37. //worker port
  38. val port = args(1)
  39. //worker memory
  40. val memory = args(2).toInt
  41. //worker cores
  42. val cores = args(3).toInt
  43. //创建config要解析的字符串
  44. val configStr: String =
  45. s"""
  46. |akka.actor.provider = "akka.remote.RemoteActorRefProvider"
  47. |akka.remote.netty.tcp.hostname = "$host"
  48. |akka.remote.netty.tcp.port = "$port"
  49. |
  50. |""".stripMargin
  51. //创建ActorSystem需要的configuration
  52. val config: Config = ConfigFactory.parseString(configStr)
  53. //创建ActorSystem
  54. val workerActorSystem: ActorSystem = ActorSystem.create("workerActorSystem", config)
  55. //创建workerActor
  56. val worker: ActorRef = workerActorSystem.actorOf(Props(new Worker(memory,cores)), "workerActor")
  57. }
  58. }

【Scala】利用akka实现Spark启动通信的更多相关文章

  1. Scala进阶之路-Spark底层通信小案例

    Scala进阶之路-Spark底层通信小案例 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.Spark Master和worker通信过程简介 1>.Worker会向ma ...

  2. 【Scala】利用Akka的actor编程模型,实现2个进程间的通信

    文章目录 步骤 一.创建maven工程,导入jar包 二.master进程代码开发 三.worker进程代码开发 四.控制台结果 步骤 一.创建maven工程,导入jar包 <propertie ...

  3. Spark --- 启动、运行、关闭过程

    // scalastyle:off println package org.apache.spark.examples import scala.math.random import org.apac ...

  4. spark 启动job的流程分析

    从WordCount開始分析 编写一个样例程序 编写一个从HDFS中读取并计算wordcount的样例程序: packageorg.apache.spark.examples importorg.ap ...

  5. Scala进阶之路-Spark本地模式搭建

    Scala进阶之路-Spark本地模式搭建 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.Spark简介 1>.Spark的产生背景 传统式的Hadoop缺点主要有以下两 ...

  6. Spark:利用Eclipse构建Spark集成开发环境

    前一篇文章“Apache Spark学习:将Spark部署到Hadoop 2.2.0上”介绍了如何使用Maven编译生成可直接运行在Hadoop 2.2.0上的Spark jar包,而本文则在此基础上 ...

  7. Scala进阶之路-Spark独立模式(Standalone)集群部署

    Scala进阶之路-Spark独立模式(Standalone)集群部署 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 我们知道Hadoop解决了大数据的存储和计算,存储使用HDFS ...

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

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

  9. 使用IDEA打包scala程序并在spark中运行

    一.首先配置ssh无秘钥登陆, 先使用这条命令:ssh-keygen,然后敲三下回车: 然后使用cd .ssh进入 .ssh这个隐藏文件夹: 再创建一个文件夹authorized_keys,使用命令t ...

随机推荐

  1. Salesforce学习 | 系统管理员Admin如何添加用户

    作为世界排名第一的CRM云计算软件,不管的是500强还是中小企业,越来越多的公司都选择使用Salesforce来分享客户信息,管理和开发具有更高收益的客户关系.Salesforce Administr ...

  2. Python-气象-大气科学-可视化绘图系列(二)——利用basemap叠加地图,并添加白化效果(代码+示例)

    本文为原创链接: https:////www.cnblogs.com/zhanling/p/12193031.html 白化单图代码: import numpy as np import xarray ...

  3. Python语言-selenium webdriver操作记录汇总

    1.控制浏览器大小 set_window_size() 设置浏览器大小 该方法有两个参数,第一个参数是宽,第二个是高 maximize_window() 设置浏览器全屏显示,无参数 chrome谷歌浏 ...

  4. Java 14 来势汹汹,这回让空指针无处遁形!!

    上篇:Java 14 之模式匹配,非常赞的一个新特性! 相信在坐的每一位 Java 程序员都遇到过空指针异常: NullPointerException(NPE),不甚其烦. 栈长之前也分享几篇避免空 ...

  5. api_DZFPKJ & api_DZFPCX(get_AES_url代码优化)

    通过AES加密网站的接口来传值,不需要手动加密字符串后复制过来传值. #coding:utf-8 import requests import re def get_aes_url(key, text ...

  6. linq 高集成化数据访问技术

    一:  新建名为linq的项目 创建 linq 1 在项目里添加文件夹 App_Code; 2 在文件夹(App_Code) 添加  名为db的    Linq To Sql 类  :一个Linq T ...

  7. shiro:集成Spring(四)

    基于[加密及密码比对器(三)]项目改造 引入相关依赖环境 shiro-spring已经包含 shiro-core和shiro-web 所以这两个依赖可以删掉 <!--shiro继承spring依 ...

  8. Deepin15.11-mysql5.7安装与配置

    目录 1.卸载 2.换源 3.安装mysql-5.7并修改密码 4.修改mysql中字符编码 deepin系统中,默认的系统源,使用apt-get install mysql-server会自动拉取m ...

  9. 我们常听到的WAL到底是什么

    什么是 WAL WAL(Write Ahead Log)预写日志,是数据库系统中常见的一种手段,用于保证数据操作的原子性和持久性. 在计算机科学中,预写式日志(Write-ahead logging, ...

  10. 一些软件的 Basic Auth 行为

    一个 WBEM 在2003年的bug I'm trying to access the WBEM service of the CIMOM on the ESX Server 3i and all m ...