Spark的通用执行流程
1.集群启动后,Worker向Master节点心跳汇报资源(CUP Core 和Memory)情况;
2.Client提交Application,根据不同的运行模式在不同的位置创建Driver进程;
3.SparkContext连接到Master,向Master注册应用并申请资源(Executor 的CPU Core和Memory);
4.Master根据SparkContext的资源申请并根据Worker心跳周期报告的信息决定在哪个Worker上资源分配,也就是Executor;
5.Worker节点创建Executor进程,Exector进行反向注册;
6.资源满足后(Exector注册完毕),SparkContext解析Application代码,创建RDD,构建DAG,并提交给DAGScheduler分解成Stage(当碰到Action算子时,就会催生job,每个job中含有1个或多个Stage),然后将Stage(或者称为TaskSet)提交给TaskScheduler,TaskScheduler负责将Task分配到相应的Worker,最后提交给Executor执行(发送到Exector的线程池中);
7.每个 Executor 会持有一个线程池,Executor 通过启动多个线程(Task)来对 RDD 的 Partition 进行并行计算,并向SparkContext 报告,直至 Task 完成。
8.所有 Task 完成后,SparkContext 向 Master 注销,释放资源。
任务失败的情况处理如下
1.Task 在 Executor 线程池中的运行情况会向 TaskScheduler 反馈,当 Task 执行失败时,会由 TaskScheduler 负责重试,将 Task 重新发送给 Executor 去执行,默认重试 3 次。如果重试 3 次依然失败,那么这个 Task 所在的 Stage 就失败了。
2.Stage 失败了会由 DAGScheduler 来负责重试,会重新发送 TaskSet 到 TaskScheduler,Stage 默认重试 4 次。如果重试 4次以后依然失败,那么这个 Job 就失败了。Job 失败则 Application 提交失败。
3.TaskScheduler 不仅能重试失败的 Task,还会重试 Straggling(落后,缓慢)的 Task(也就是执行速度比其他 Task 慢太多的Task)。如果有运行缓慢的 Task 那么 TaskScheduler 会启动一个新的 Task 来与这个运行缓慢的 Task 执行相同的处理逻辑。两个 Task 哪个先执行完,就以哪个 Task 的执行结果为准。这就是 Spark 的推测执行机制。在 Spark 中推测执行默认是关闭的。推测执行可以通过 spark.speculation 属性来配置。