Spark2.2源码之Application注册机制
注意: 1.6版本的spark很明显重构了大量了代码、注册和调度机制优化了不少。这里主要讲的是Spark自身的Standalone模式。
大概流程: 这里分析的注册机制主要是讲当Master Receive到Regist Request之后所做的操作
-
1、Application Regist classPath:org.apache.spark.deploy.master.Master
- 当Master的RpcEndpoint接收到app注册消息后(模式匹配),会根据参数ApplicationDescription来创建ApplicationInfo
- 然后保存该app的Rpc通信地址到Master的成员变量addressToApp,这就是注册操作。(只保存到内存)
- 进行一次持久化引擎的保存操作,方便Master恢复机制读取数据。
- 返回Driver注册成功的结果,包含了appId,和Master的通信对象RpcEndpointRef
- 1.1 接收注册消息
//1.6版本后、为了弱化Akka,spark采用RpcEnv方式来做RPC通信,这里是接收消息的方法
override def receive: PartialFunction[Any, Unit] = {
case ElectedLeader =>
case CompleteRecovery =>
case RevokedLeadership =>
// ..........................
case RegisterApplication(description, driver) => //这里就是接收注册appd的消息
if (state == RecoveryState.STANDBY) {
// 如果当前master是备用的,则直接忽略,不发送任何消息
} else {
// 创建Application
val app = createApplication(description, driver)
// 把创建好的App注册到Master里便于管理
registerApplication(app)
// 使用持久化引擎来保存当前app的状态
persistenceEngine.addApplication(app)
// 向提交这个app的driver返回注册结果、地址等.
driver.send(RegisteredApplication(app.id, self))
// 这个方法很重要,在 《Spark1.6源码之Master调度机制》里会讲到
schedule()
}
}
1.2 创建Application
//接收ApplicationDescription类的对象,这个类里包含了启动这个App的详细参数信息(name、maxCores、memoryPerExecutorMB...),这个对象作为ApplicationInfo类的属性当做引用使用
private def createApplication(desc: ApplicationDescription, driver: RpcEndpointRef):
ApplicationInfo = {
val now = System.currentTimeMillis()
val date = new Date(now)
val appId = newApplicationId(date)
// ApplicationInfo才是创建真正的Application,这个类有一些操作Executor的方法
new ApplicationInfo(now, appId, desc, date, driver, defaultCores)
}
1.3 注册Application
private def registerApplication(app: ApplicationInfo): Unit = {
val appAddress = app.driver.address //拿到提交这个app的Driver的通信地址
//addressToApp变量是HashMap<RpcAddress, ApplicationInfo>,保存着启动每个app所对应的dreiver地址对应关系,如果已经存在,说明这个地址已经启动了app,不予重新启动
if (addressToApp.contains(appAddress)) {
logInfo("Attempted to re-register application at same address: " + appAddress)
return
}
//统计系统相关、暂不讨论
applicationMetricsSystem.registerSource(app.appSource)
apps += app //把当前app加入所有app集合序列里
idToApp(app.id) = app // id -> app 的对应关系集合
endpointToApp(app.driver) = app //endpointToApp存的是HashMap<RpcEndpointRef, ApplicationInfo>,保存了每个消息发送方所对应的app
addressToApp(appAddress) = app
waitingApps += app //这个集合保存了需要处理的app集合、这个集合是随时增减的。
if (reverseProxy) {
webUi.addProxyTargets(app.id, app.desc.appUiUrl)
}
}