【原】 Spark中Worker源码分析(一)
Worker作为对于Spark集群的健壮运行起着举足轻重的作用,作为Master的奴隶,每15s向Master告诉自己还活着,一旦主人(Master》有了任务(Application),立马交给属于它的奴隶们(Workers),那么奴隶们就会数数自己有多少家当(比如内存、核数),量力而行地交给主人完成的任务,如果奴隶不量力而行在执行任务过程中不幸死了的话,作为主人的Master只会等待60s,如果奴隶在这生死攸关的紧要关头不理睬主人,那么主人只能认为它死了,那么就会把它抛弃了。下面,我们一起了解一下Worker究竟有哪些不为人知的故事。
1.家当(静态属性)
我们只列出一些重要的属性:
1.一个守护单线程的调度器用于在特殊的时间发送消息,执行的任务包括:向Master注册Worker信息、发送心跳信息、定期清理任务等。
private val forwordMessageScheduler =
ThreadUtils.newDaemonSingleThreadScheduledExecutor("worker-forward-message-scheduler")
2.一个独立的线程用于清理工作空间,执行任务:定期清理执行过程中创建的本地文件。
private val cleanupThreadExecutor = ExecutionContext.fromExecutorService(
ThreadUtils.newDaemonSingleThreadExecutor("worker-cleanup-thread"))
3.shuffle服务默认没有开启除非用户自己配置,之所以会开启外部的Shuffle服务,是为了避免Executor进程任务过重,导致不能为其他的Executor提供Shuffle数据,影响任务的执行。比如,如果使用YARN模式时,可以在yarn-site.xml文件中配置及其端口号,从而在NodeManger上开启Shuffle服务,减轻Executor的负担。
private val shuffleService = new ExternalShuffleService(conf, securityMgr)
4.一个masters的线程池。因为master注册Worker是一个阻塞操作,所以这个线程池必须能同时创建"masterRpcAddresses.size"大小的线程,这样我们就能将worker注册到所有的master上。
private val registerMasterThreadPool = new ThreadPoolExecutor(
0,
masterRpcAddresses.size, // Make sure we can register with all masters at the same time
60L, TimeUnit.SECONDS,
new SynchronousQueue[Runnable](),
ThreadUtils.namedThreadFactory("worker-register-master-threadpool"))
2.技能(方法)
由于Worker本质上是一个RpcEndpoint,所以我们按照它的声明周期进行介绍。
1.构造函数就是Worker默认的构造器
2.onStart方法
<code>
//worker的启动
override def onStart() {
assert(!registered)
logInfo("Starting Spark worker %s:%d with %d cores, %s RAM".format(
host, port, cores, Utils.megabytesToString(memory)))
logInfo(s"Running Spark version ${org.apache.spark.SPARK_VERSION}")
logInfo("Spark home: " + sparkHome)
createWorkDir()
//如果用户已经配置外部的Shuffle,那么就启动该服务
shuffleService.startIfEnabled()
//该WebUI只仅限于Standalone模式下
webUi = new WorkerWebUI(this, workDir, webUiPort)
webUi.bind()
//将worker注册到master上,详情如下(1)
registerWithMaster()
metricsSystem.registerSource(workerSource)
metricsSystem.start()
//metricsSystem启动后,将worker的metrics的servlet handler添加到web ui
metricsSystem.getServletHandlers.foreach(webUi.attachHandler)
}
</code>
(1)将worker注册到master上的registerWithMaster()代码如下所示:
<code>
private def registerWithMaster() {
//如果work与master可能多次失去连接,所以不要尝试太多次的注册
registrationRetryTimer match {
case None =>
registered = false
//将woker注册到所有的master上返回一个Future的数组,详情如下(2)
registerMasterFutures = tryRegisterAllMasters()
connectionAttemptCount = 0
//一个单线程不定时向master发送注册信息
registrationRetryTimer = Some(forwordMessageScheduler.scheduleAtFixedRate(
new Runnable {
override def run(): Unit = Utils.tryLogNonFatalError {
Option(self).foreach(_.send(ReregisterWithMaster))
}
},
INITIAL_REGISTRATION_RETRY_INTERVAL_SECONDS,
INITIAL_REGISTRATION_RETRY_INTERVAL_SECONDS,
TimeUnit.SECONDS))
case Some(_) =>
logInfo("Not spawning another attempt to register with the master, since there is an" +
" attempt scheduled already.")
}
}
</code>
(2)tryRegisterAllMasters代码如下:
<code>
//将worker注册到所有的master上面
private def tryRegisterAllMasters(): Array[JFuture[_]] = {
masterRpcAddresses.map { masterAddress =>
registerMasterThreadPool.submit(new Runnable {
override def run(): Unit = {
try {
logInfo("Connecting to master " + masterAddress + "...")
//在Client的Rpc中根据master的systemname、address、endpointname返回一个master的远程引用
val masterEndpoint =
rpcEnv.setupEndpointRef(Master.SYSTEM_NAME, masterAddress, Master.ENDPOINT_NAME)
//调用master的远程引用将worker注册到master上
masterEndpoint.send(RegisterWorker(
workerId, host, port, self, cores, memory, webUi.boundPort, publicAddress))
} catch {
case ie: InterruptedException => // Cancelled
case NonFatal(e) => logWarning(s"Failed to connect to master $masterAddress", e)
}
}
})
}
}
</code>
3.onStop()方法,把关于Worker的一切都停止掉,比如线程、executors、drivers、shuffleService等
<code>
override def onStop() {
cleanupThreadExecutor.shutdownNow()
metricsSystem.report()
cancelLastRegistrationRetry()
forwordMessageScheduler.shutdownNow()
registerMasterThreadPool.shutdownNow()
executors.values.foreach(_.kill())
drivers.values.foreach(_.kill())
shuffleService.stop()
webUi.stop()
metricsSystem.stop()
}
</code>
还有一个很重要的receive方法,都放到这儿可能有点拥挤,留到下一篇吧。
【原】 Spark中Worker源码分析(一)的更多相关文章
- 【原】 Spark中Worker源码分析(二)
继续前一篇的内容.前一篇内容为: Spark中Worker源码分析(一)http://www.cnblogs.com/yourarebest/p/5300202.html 4.receive方法, r ...
- 【原】Spark中Client源码分析(二)
继续前一篇的内容.前一篇内容为: Spark中Client源码分析(一)http://www.cnblogs.com/yourarebest/p/5313006.html DriverClient中的 ...
- 【原】Spark中Master源码分析(二)
继续上一篇的内容.上一篇的内容为: Spark中Master源码分析(一) http://www.cnblogs.com/yourarebest/p/5312965.html 4.receive方法, ...
- 【原】Spark中Master源码分析(一)
Master作为集群的Manager,对于集群的健壮运行发挥着十分重要的作用.下面,我们一起了解一下Master是听从Client(Leader)的号召,如何管理好Worker的吧. 1.家当(静态属 ...
- Spark中决策树源码分析
1.Example 使用Spark MLlib中决策树分类器API,训练出一个决策树模型,使用Python开发. """ Decision Tree Classifica ...
- 【原】Spark中Client源码分析(一)
在Spark Standalone中我们所谓的Client,它的任务其实是由AppClient和DriverClient共同完成的.AppClient是一个允许app(Client)和Spark集群通 ...
- Spark Scheduler模块源码分析之DAGScheduler
本文主要结合Spark-1.6.0的源码,对Spark中任务调度模块的执行过程进行分析.Spark Application在遇到Action操作时才会真正的提交任务并进行计算.这时Spark会根据Ac ...
- Spark RPC框架源码分析(三)Spark心跳机制分析
一.Spark心跳概述 前面两节中介绍了Spark RPC的基本知识,以及深入剖析了Spark RPC中一些源码的实现流程. 具体可以看这里: Spark RPC框架源码分析(二)运行时序 Spark ...
- Spark Scheduler模块源码分析之TaskScheduler和SchedulerBackend
本文是Scheduler模块源码分析的第二篇,第一篇Spark Scheduler模块源码分析之DAGScheduler主要分析了DAGScheduler.本文接下来结合Spark-1.6.0的源码继 ...
随机推荐
- css实现div块半透明
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- dedecms 获取文章发布时间和获取文章最后更新时间
文章发布时间:[field:senddate function=MyDate('m-d',@me)/] 文章最后更新时间:[field:pubdate function=MyDate('m-d',@m ...
- java实现的JDBCTemplate工具
1.DButil import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; impor ...
- .NET中的加密算法总结(自定义加密Helper类续)
1.1.1 摘要 相信许多人都使用过.NET提供的加密算法,而且在使用的过程我们必须了解每种加密算法的特点(对称或非对称,密钥长度和初始化向量等等).我也看到过很多人写过.NET中加密算法总结,但我发 ...
- ASP.net 的URL路由选择(System.Web.Routing.dll)
System.Web.Routing是.net 3.5sp1中新增的一个dll,用它提拱的类可以很方便的实现url的映射,在asp.net WebFrom的编程中可以使客户端请求的URL变得更加的&q ...
- EasyUI 关于IE使用window组件上传文件
有时候IE会对使用window组件上传文件(第二次)不生效,解决方案是: 将该window每次打开的时候,使用: $('#adUploadWindow').window('refresh', 'pan ...
- php smarty 配置四个存放目录
require("Smarty.class.php"); $smarty = new Smarty(); $smarty -> template_dir = "./ ...
- ASP.NET控件Button (e.CommandArgument的使用方法)
e.CommandArgument的使用方法 1. 在 Web 窗体页上显示普通按钮 (Button) 控件. <asp:Button id="MyButton" Text= ...
- Android USB Host 与 HID 之通讯方法
Android USB Host与HID通讯,就目前Google Developer提供的方法有bulkTransfer()与controlTransfer(),看是简简单单的两个方法,要实现真正的通 ...
- HANA内存数据库与oracle数据库的性能比较
链接: http://wenku.it168.com/redian/hana/ 1.传统磁盘数据库的基本访问模式.为了提高性能在产品和应用之间会加入缓存的内存区域.传统数据库性能瓶颈主要出现在一个是内 ...