Spark启动流程(Standalone)- master源码
Master源码
package org.apache.spark.deploy.master
//伴生类
private[deploy] class Master(
override val rpcEnv: RpcEnv,
address: RpcAddress,
webUiPort: Int,
val securityMgr: SecurityManager,
val conf: SparkConf)
extends ThreadSafeRpcEndpoint with Logging with LeaderElectable
{
...
}
//伴生对象
private[deploy] object Master extends Logging{
val SYSTEM_NAME = "sparkMaster"
val ENDPOINT_NAME = "Master" // 启动 Master 的入口函数
def main(argStrings: Array[String]) {
Utils.initDaemon(log)
val conf = new SparkConf
// 构建用于参数解析的实例
//--host hadoop201 --port 7077 --webui-port 8080
val args = new MasterArguments(argStrings, conf)
// 启动 RPC 通信环境和 MasterEndPoint(通信终端)
//<<1>>
val (rpcEnv, _, _): (RpcEnv, Int, Option[Int]) = startRpcEnvAndEndpoint(args.host, args.port, args.webUiPort, conf)
rpcEnv.awaitTermination()
}
...
}
<< 1 >>、启动Mater返回一个三元组
/**
* Start the Master and return a three tuple of:
* 启动 Master, 并返回一个三元组
* (1) The Master RpcEnv
* (2) The web UI bound port
* (3) The REST server bound port, if any
*/
def startRpcEnvAndEndpoint(
host: String,
port: Int,
webUiPort: Int,
conf: SparkConf): (RpcEnv, Int, Option[Int]) = {
val securityMgr = new SecurityManager(conf)
// 创建 Master 端的 RpcEnv 环境, 并启动 RpcEnv
// 参数: sparkMaster hadoop201 7077 conf securityMgr
// 返回值 的实际类型是: NettyRpcEnv
//<< 1.1 >>
val rpcEnv: RpcEnv = RpcEnv.create(SYSTEM_NAME, host, port, conf, securityMgr)
// 创建 Master对象, 该对象就是一个 RpcEndpoint, 在 RpcEnv 中注册这个 RpcEndpoint
// 返回该 RpcEndpoint 的引用, 使用该引用来接收信息和发送信息
//<< 1.2 >>
val masterEndpoint: RpcEndpointRef = rpcEnv.setupEndpoint(ENDPOINT_NAME,
new Master(rpcEnv, rpcEnv.address, webUiPort, securityMgr, conf))
// 向 Master 的通信终端发法请求,获取 BoundPortsResponse 对象
// BoundPortsResponse 是一个样例类包含三个属性: rpcEndpointPort webUIPort restPort
val portsResponse: BoundPortsResponse = masterEndpoint.askWithRetry[BoundPortsResponse](BoundPortsRequest)
(rpcEnv, portsResponse.webUIPort, portsResponse.restPort)
}
<< 1.1 >> RpcEnv的创建
def create(
name: String,
bindAddress: String,
advertiseAddress: String,
port: Int,
conf: SparkConf,
securityManager: SecurityManager,
clientMode: Boolean): RpcEnv = {
// 保存 RpcEnv 的配置信息
val config = RpcEnvConfig(conf, name, bindAddress, advertiseAddress, port, securityManager,
clientMode)
// 创建 NettyRpcEvn
//<< 1.1.1 >>
new NettyRpcEnvFactory().create(config)
}
真正的创建是调用NettyRpcEnvFactory 的 create 方法创建
创建NettyRpcEnv的时候,会创建消息分发器,收件箱和存储远程地址与发件箱的Map
RpcEnv.scala
<< 1.1.1 >> NettyRpcEnvFactory ( NettyRpcEnv .scala)
private[rpc] class NettyRpcEnvFactory extends RpcEnvFactory with Logging {
/*
创建 NettyRpcEnv, 并且启动为后台程序
*/
def create(config: RpcEnvConfig): RpcEnv = {
val sparkConf: SparkConf = config.conf
// Use JavaSerializerInstance in multiple threads is safe. However, if we plan to support
// KryoSerializer in future, we have to use ThreadLocal to store SerializerInstance
// 用于 Rpc传输对象时的序列化
val javaSerializerInstance: JavaSerializerInstance = new JavaSerializer(sparkConf)
.newInstance()
.asInstanceOf[JavaSerializerInstance]
// 实例化 NettyRpcEnv
val nettyEnv = new NettyRpcEnv(
sparkConf,
javaSerializerInstance,
config.advertiseAddress,
config.securityManager)
if (!config.clientMode) {
// 定义 NettyRpcEnv 的启动函数
val startNettyRpcEnv: Int => (NettyRpcEnv, Int) = { actualPort =>
nettyEnv.startServer(config.bindAddress, actualPort)
(nettyEnv, nettyEnv.address.port)
}
try {
// 启动 NettyRpcEnv
Utils.startServiceOnPort(config.port, startNettyRpcEnv, sparkConf, config.name)._1
} catch {
case NonFatal(e) =>
nettyEnv.shutdown()
throw e
}
}
nettyEnv
}
}
<< 1.2 >> Master伴生类(Master 端的 RpcEndpoint 启动)
Master是一个RpcEndpoint.
他的生命周期方法是: constructor -> onStart -> receive* -> onStop
onStart 主要代码片段
// 创建 WebUI 服务器
webUi = new MasterWebUI(this, webUiPort) // 按照固定的频率去启动线程来检查 Worker 是否超时. 其实就是给自己发信息: CheckForWorkerTimeOut
// 默认是每分钟检查一次.
checkForWorkerTimeOutTask = forwardMessageThread.scheduleAtFixedRate(new Runnable {
override def run(): Unit = Utils.tryLogNonFatalError {
// 在 receive 方法中对 CheckForWorkerTimeOut 进行处理
//<< 1.2.1 >>
self.send(CheckForWorkerTimeOut)
}
}, 0, WORKER_TIMEOUT_MS, TimeUnit.MILLISECONDS) private val WORKER_TIMEOUT_MS = conf.getLong("spark.worker.timeout", 60) * 1000
<< 1.2.1 >> 检查并移除超时的worker
/** Check for, and remove, any timed-out workers */
private def timeOutDeadWorkers() {
// Copy the workers into an array so we don't modify the hashset while iterating through it
val currentTime = System.currentTimeMillis()
// 把超时的 Worker 从 workers 中移除
//过滤出来要移除的worker:(上次心跳时间 小于 当前时间 减去 超时时间 )即为超时
val toRemove = workers.filter(_.lastHeartbeat < currentTime - WORKER_TIMEOUT_MS).toArray
for (worker <- toRemove) {
// 如果 worker 的状态不是 DEAD
if (worker.state != WorkerState.DEAD) {
logWarning("Removing %s because we got no heartbeat in %d seconds".format(
worker.id, WORKER_TIMEOUT_MS / 1000))
removeWorker(worker) //
} else {
if (worker.lastHeartbeat < currentTime - ((REAPER_ITERATIONS + 1) * WORKER_TIMEOUT_MS)) {
workers -= worker // we've seen this DEAD worker in the UI, etc. for long enough; cull it
}
}
}
}
Spark启动流程(Standalone)- master源码的更多相关文章
- Phalcon的Mvc结构及启动流程(部分源码分析)
Phalcon本身有支持创建多种形式的Web应用项目以应对不同场景,包括迷你应用.单模块标准应用.以及较复杂的多模块应用 创建项目 Phalcon环境配置安装后,可以通过命令行生成一个标准的Phalc ...
- Phalcon Framework的Mvc结构及启动流程(部分源码分析)
创建项目 Phalcon环境配置安装后,可以通过命令行生成一个标准的Phalcon多模块应用 phalcon project eva --type modules入口文件为public/index.p ...
- 《深入理解Spark:核心思想与源码分析》——SparkContext的初始化(叔篇)——TaskScheduler的启动
<深入理解Spark:核心思想与源码分析>一书前言的内容请看链接<深入理解SPARK:核心思想与源码分析>一书正式出版上市 <深入理解Spark:核心思想与源码分析> ...
- 【原】Spark中Master源码分析(二)
继续上一篇的内容.上一篇的内容为: Spark中Master源码分析(一) http://www.cnblogs.com/yourarebest/p/5312965.html 4.receive方法, ...
- 《深入理解Spark:核心思想与源码分析》(第2章)
<深入理解Spark:核心思想与源码分析>一书前言的内容请看链接<深入理解SPARK:核心思想与源码分析>一书正式出版上市 <深入理解Spark:核心思想与源码分析> ...
- 《深入理解Spark:核心思想与源码分析》(前言及第1章)
自己牺牲了7个月的周末和下班空闲时间,通过研究Spark源码和原理,总结整理的<深入理解Spark:核心思想与源码分析>一书现在已经正式出版上市,目前亚马逊.京东.当当.天猫等网站均有销售 ...
- Spark之SQL解析(源码阅读十)
如何能更好的运用与监控sparkSQL?或许我们改更深层次的了解它深层次的原理是什么.之前总结的已经写了传统数据库与Spark的sql解析之间的差别.那么我们下来直切主题~ 如今的Spark已经支持多 ...
- 《深入理解Spark:核心思想与源码分析》一书正式出版上市
自己牺牲了7个月的周末和下班空闲时间,通过研究Spark源码和原理,总结整理的<深入理解Spark:核心思想与源码分析>一书现在已经正式出版上市,目前亚马逊.京东.当当.天猫等网站均有销售 ...
- 《深入理解Spark:核心思想与源码分析》正式出版上市
自己牺牲了7个月的周末和下班空闲时间,通过研究Spark源码和原理,总结整理的<深入理解Spark:核心思想与源码分析>一书现在已经正式出版上市,目前亚马逊.京东.当当.天猫等网站均有销售 ...
随机推荐
- JAVA笔记28-正则表达式(补充、不重要)
一.Greedy(贪婪的)尽可能多的匹配,Reluctant(不情愿的)尽可能少的匹配.Possessive(独占的)不常用. Greedy 数量词 X? X,一次或一次也没有 X* X,零次或多次 ...
- 【NOIP2017模拟6.25】小W的动漫
题目 小W最近迷上了日本动漫,每天都有无数部动漫的更新等着他去看,所以他必须将所有的动漫排个顺序,当然,虽然有无数部动漫,但除了1号动漫,每部动漫都有且仅有一部动漫是它的前传(父亲),也就是说,所有的 ...
- 【leetcode&CN&竞赛】1198.Find Smallest Common Element in All Rows
题目如下: 给你一个矩阵 mat,其中每一行的元素都已经按 递增 顺序排好了.请你帮忙找出在所有这些行中 最小的公共元素. 如果矩阵中没有这样的公共元素,就请返回 -1. 示例: 输入:mat = [ ...
- 两句话掌握 Python 最难知识点——元类
千万不要被所谓“元类是99%的python程序员不会用到的特性”这类的说辞吓住.因为每个中国人,都是天生的元类使用者 学懂元类,你只需要知道两句话: 道生一,一生二,二生三,三生万物 我是谁?我从哪来 ...
- jsonp跨域实例
一.什么是跨域 二.如何解决跨域 1.前端常用 JSONP 2.服务器端配置 HTTP 协议的 header 解析 三.JSONP实现的实例 <!DOCTYPE html> <htm ...
- Send Email
private string SendEmail(string mailTo, string body, ref int sendresult) { string errorEmailAddress ...
- 建立PHP的本地调试环境PHP基础教程
对于windows平台而言,PHP供给了一个安装程序,但是这个安装程序是不能直接运行来建立个人服务器平台的,而是必需嵌进现有的服务器平台,如:Windows NT下的IIS或Windows下的PWS, ...
- Python连接MySQL之Python库pymysql
连接数据库 pymysql连接数据库的方式和使用sqlite的方式基本相同: 使用connect创建连接对象 connect.cursor创建游标对象,SQL语句的执行基本都在游标上进行 cursor ...
- html canvas标签 语法
html canvas标签 语法 canvas是什么意思? 作用:定义图形,比如图表和其他图像. 说明:<canvas> 标签只是图形容器,通过脚本 (通常是JavaScript)来完成, ...
- Maven Waring : GroupId is duplicate of parent groupId 和 Version is duplicate of parent version
问题描述: 新项目在创建的时候,因为用到了分模块的,所以导致子模块的pom文件,报了 如下警告: 解决办法: 直接 Window --> Preferences --> Maven -- ...