当触发一个 RDD 的 action 操作(以 count 为例)时,整个执行链路大致如下:
- org.apache.spark.rdd.RDD#count
- org.apache.spark.SparkContext#runJob
- org.apache.spark.scheduler.DAGScheduler#runJob
- org.apache.spark.scheduler.DAGScheduler#submitJob
- org.apache.spark.scheduler.DAGSchedulerEventProcessActor#receive(JobSubmitted)
- org.apache.spark.scheduler.DAGScheduler#handleJobSubmitted
其中步骤五中的 DAGSchedulerEventProcessActor 是 DAGScheduler 的消息处理器,负责接收并分发各类调度事件。一旦进入 handleJobSubmitted 方法,核心逻辑便开始了。
这里需要特别注意,Spark 并不是直接提交任务,而是先进行依赖分析。DAGScheduler 会根据宽依赖(Shuffle Dependency)将计算图切分为不同的 Stage。每个 Stage 内部包含一组可以并行执行的 TaskSet。这种划分机制决定了任务的粒度,直接影响着资源利用率和容错效率。
接着,SchedulerBackend 会接收这些 TaskSet,并将其下发给具体的 Executor。在这个过程中,资源分配和任务重试机制也会介入。理解这一流程对于优化 Spark 性能至关重要,特别是当遇到数据倾斜或 Shuffle 瓶颈时,回溯到这个阶段往往能找到根源。
后续的步骤涉及 TaskScheduler 的具体实现,以及 Driver 端如何与 Executor 通信,但这已经超出了当前调用的范围。重点在于把握从 Action 触发到 Stage 生成的这一关键转化过程。通过阅读这部分源码,能更清晰地看到 Spark 是如何将高层的抽象算子转化为底层可执行的物理计划。

