程序入口,前面参数初始化略过 。。。。
首先调用createSparkEnv 创建env
// Create the Spark execution environment (cache, map output tracker, etc)
_env = createSparkEnv(_conf, isLocal, listenerBus)
SparkEnv.set(_env)
1.首先来看listenerBus
事件对象
事件监听模式 事件源
时间监听器
sparkContext中初始化该LiveListenerBus
// An asynchronous listener bus for Spark events
private[spark] val listenerBus = new LiveListenerBus(this)
//Asynchronously passes SparkListenerEvents to registered SparkListeners.
//异步地将SparkListenerEvents传递给已经注册过的SparkListeners
LiveListenerBus :
//用于放置 SparkListenerEvent 事件的阻塞队列 容量可通过参数设置
private lazy val eventQueue = new LinkedBlockingQueue[SparkListenerEvent]
//用于标明LiveListenerBus是否启动
private val started = new AtomicBoolean(false)
//用于标明LiveListenerBus是否停止
private val stopped = new AtomicBoolean(false)
//用于统计删除event的数据,每当日志打印了该值,则重置为0
private val droppedEventsCounter = new AtomicLong(0L)
//用于记录打印droppedEventsCounter 的时间戳
@volatile private var lastReportTimestamp = 0L
//用于标明当前listenerThread正在处理event
private var processingEvent = false
//用于标明队列是否已满,导致新的事件不能进入队列从而被删除
private val logDroppedEvent = new AtomicBoolean(false)
//用于当有新的事件到来时释放信号量,当对事件进行处理时获取信号量
private val eventLock = new Semaphore(0)
//处理事件的线程
private val listenerThread = new Thread(name) {
setDaemon(true)
override def run(): Unit = Utils.tryOrStopSparkContext(sparkContext) {
LiveListenerBus.withinListenerThread.withValue(true) {
while (true) {
//获取信号量,当有信号量存在时说明还有未处理的event
eventLock.acquire()
self.synchronized {
//设置当前正在处理event
processingEvent = true
}
try {
//从eventQueue中获取event
val event = eventQueue.poll
if (event == null) {
// Get out of the while loop and shutdown the daemon thread
if (!stopped.get) {
throw new IllegalStateException(“Polling null from eventQueue means” +
" the listener bus has been stopped. So stopped must be true")
}
return
}
//使用父类ListenerBus的postToAll将event发送到注册过的所有listener上
postToAll(event)
} finally {
self.synchronized {
//将当前正在处理event状态标记为false
processingEvent = false
}
}
}
}
}
}
listener 相关博客 https://www.pianshen.com/article/32472081/
2.接着来看createSparkEnv方法
该方法最终调用SparkEnv的create方法,进入方法内部,最终 new SparkEnv(…)来创建了SparkEnv
val envInstance = new SparkEnv(
executorId,
rpcEnv,
serializer,
closureSerializer,
serializerManager,
mapOutputTracker,
shuffleManager,
broadcastManager,
blockManager,
securityManager,
metricsSystem,
memoryManager,
outputCommitCoordinator,
conf)
到此,SparkEnv对象初始化完成
3.开始创建TaskScheduler
// Create and start the scheduler
val (sched, ts) = SparkContext.createTaskScheduler(this, master, deployMode)
根据不同模式创建不同的TaskScheduler 和 SchedulerBackend
4.创建DAGScheduler,最终使用 SparkContext对象创建DAGScheduler
_dagScheduler = new DAGScheduler(this) ====>>>> def this(sc: SparkContext) = this(sc, sc.taskScheduler)
5.将DAGScheduler对象注入到taskScheduler中
taskScheduler.setDAGScheduler(this)
6.启动TaskScheduler
_taskScheduler.start()
RpcEndPoint 表示需要通信的对象
RpcEndpointRef 对远程RpcEndpoint的一个引用,需要获取引用之后,通过该引用发送消息
RpcEnv 为RpcEndPoint提供处理消息的环境,负责RpcEndPoint整个生命周期的管理
相关博客 https://blog.csdn.net/qq_35078688/article/details/88342371
createSparkEnv(_conf, isLocal, listenerBus) 中通过 SparkEnv 创建Driver端的运行环境SparkEnv.createDriverEnv(conf, isLocal, listenerBus, SparkContext.numDriverCores(master))
通过set方法将创建好的DriverEnv拿过来
def set(e: SparkEnv) {
env = e
}
object SparkEnv extends Logging {
@volatile private var env: SparkEnv = _
…
}
接着来看 createSparkEnv 方法
private[spark] def createSparkEnv(
conf: SparkConf,
isLocal: Boolean,
listenerBus: LiveListenerBus): SparkEnv = {
SparkEnv.createDriverEnv(conf, isLocal, listenerBus, SparkContext.numDriverCores(master))
}
第一步:创建了Driver端的运行环境 _env :
SparkEnv.createDriverEnv(conf, isLocal, listenerBus, SparkContext.numDriverCores(master)
第二步:创建taskScheduler
val (sched, ts) = SparkContext.createTaskScheduler(this, master, deployMode)
_schedulerBackend = sched
_taskScheduler = ts
第三步:创建DagScheduler
_dagScheduler = new DAGScheduler(this)
创建时需要taskScheduler
def this(sc: SparkContext) = this(sc, sc.taskScheduler)
第四步:启动taskScheduler _taskScheduler.start()
未完