Spark-Core源码学习记录
该系列作为Spark源码回顾学习的记录,旨在捋清Spark分发程序运行的机制和流程,对部分关键源码进行追踪,争取做到知其所以然,对枝节部分源码仅进行文字说明,不深入下钻,避免混淆主干内容。
本文为RpcEnv、RpcEndpoint、RpcEndpointRef
相关内容的介绍,此为阅读后续源码的基础。
自Spark 2.1.0之后的底层实现只有Netty,移除了Akka的依赖,下面就从create方法开始追踪源码:
val rpcEnv = RpcEnv.create(SYSTEM_NAME, host, port, conf, securityMgr)
val masterEndpoint = rpcEnv.setupEndpoint(ENDPOINT_NAME,new Master(rpcEnv, rpcEnv.address, webUiPort, securityMgr, conf))
val portsResponse = masterEndpoint.askSync[BoundPortsResponse](BoundPortsRequest)
RpcEnv
首先是静态类RpcEnv,包含两个重载的create方法,其中RpcEnvConfig
是一个模板类,因此create方法最终仍是通过工厂类NettyRpcEnvFactory
的create方法进行初始化。
/**
* A RpcEnv implementation must have a [[RpcEnvFactory]] implementation with an empty constructor
* so that it can be created via Reflection.
*/
private[spark] object RpcEnv {
def create(name: String,bindAddress: String,advertiseAddress: String,port: Int,conf: SparkConf,securityManager: SecurityManager,numUsableCores: Int,clientMode: Boolean): RpcEnv = {
//RpcEnvConfig是一个模板类
val config = RpcEnvConfig(conf, name, bindAddress, advertiseAddress, port, securityManager, numUsableCores, clientMode)
new NettyRpcEnvFactory().create(config)
}
}
查看工厂类的create方法:
private[rpc] class NettyRpcEnvFactory extends RpcEnvFactory with Logging {
def create(config: RpcEnvConfig): RpcEnv = {
val sparkConf = config.conf
// 初始化序列器
val javaSerializerInstance =
new JavaSerializer(sparkConf).newInstance().asInstanceOf[JavaSerializerInstance]
// 实例化NettyRpcEnv,该部分为重要内容
val nettyEnv = new NettyRpcEnv(sparkConf, javaSerializerInstance, config.advertiseAddress, config.securityManager, config.numUsableCores)
if (!config.clientMode) {
// clientMode默认为false
//此处为伪代码,便于理解
nettyEnv.startServer(config.bindAddress, config.port)
}
nettyEnv
}
}
进入NettyRpcEnv实例化的部分源码,此处初始化了一个Dispatcher实例对象
private[netty] class NettyRpcEnv(val conf: SparkConf,javaSerializerInstance: JavaSerializerInstance,host: String,securityManager: SecurityManager,numUsableCores: Int) extends RpcEnv(conf) with Logging {
//初始化一个分配器,此为关键调度组件
private val dispatcher: Dispatcher = new Dispatcher(this, numUsableCores)
//初始化一个transportContext实例,以供后续分发程序使用
private val transportContext = new TransportContext(transportConf,new NettyRpcHandler(dispatcher, this, streamManager))
def startServer(bindAddress: String, port: Int)