Spark的作业提交流程简介

这是自己读取源码并结合他人的总结,写的大概的流程,仅供参考

第一部分:大体流程

(1)将我们编写的程序打成jar包
(2)调用spark-submit脚本提交任务到集群上运行
(3)运行sparkSubmit的main方法,在这个方法中通过反射的方式创建我们编写的主类的实例对象,然后调用main方法,开始执行我们的代码(注意,我们的
spark程序中的driver就运行在sparkSubmit进程中)
(4)当代码运行到创建SparkContext对象时,那就开始初始化SparkContext
对象了
(5)在初始化SparkContext对象的时候,会创建两个特别重要的对象,分别是:
DAGScheduler 和TaskScheduler【DAGScheduler的作用】将RDD的依赖切分成一个一个的stage,然后将stage作为taskSet提交给DriverActor
(6)在构建TaskScheduler的同时,会创建两个非常重要的对象,分别是DriverActor和ClientActor
【clientActor的作用】向master注册用户提交的任务
【DriverActor的作用】接受executor的反向注册,将任务提交给executor
(7)当ClientActor启动后,会将用户提交的任务和相关的参数封装到ApplicationDescription对象中,然后提交给master进行任务的注册
(8)当 master 接受到 clientActor 提交的任务请求时,会将请求参数进行解析,并封装成Application,然后将其持久化,然后将其加入到任务队列waitingApps 中
(9)当轮到我们提交的任务运行时,就开始调用 schedule(),进行任务资源的调度
(10)master 将调度好的资源封装到 launchExecutor 中发送给指定的 worker
(11)worker 接受到 Master 发送来的 launchExecutor 时,会将其解压并封装到 ExecutorRunner中,然后调用这个对象的 start(), 启动 Executor
(12)Executor 启动后会向 DriverActor 进行反向注册
(13)driverActor 会发送注册成功的消息给 Executor
(14)Executor 接受到 DriverActor 注册成功的消息后会创建一个线程池,用于执行 DriverActor发送过来的 task 任务
(15)当属于这个任务的所有的 Executor 启动并反向注册成功后,就意味着运行这个任务的环境已经准备好了,driver 会结束 SparkContext 对象的初始化,也就意味着 new SparkContext这句代码运行完成
(16)当初始化 sc 成功后,driver 端就会继续运行我们编写的代码,然后开始创建初始的 RDD,然后进行一系列转换操作,当遇到一个 action 算子时,也就意味着触发了一个 job
(17)driver 会将这个 job 提交给 DAGScheduler
(18)DAGScheduler 将接受到的 job,从最后一个算子向前推导,将 DAG 依据宽依赖划分成一个一个的 stage,然后将 stage 封装成 taskSet,并将 taskSet 中的 task 提交给 DriverActor
(19)DriverActor 接受到 DAGScheduler 发送过来的 task,会拿到一个序列化器,对 task 进行序列化,然后将序列化好的 task 封装到 launchTask 中,然后将 launchTask 发送给指定的Executor
(20)Executor 接受到了 DriverActor 发送过来的 launchTask 时,会拿到一个反序列化器,对launchTask 进行反序列化,封装到 TaskRunner 中,然后从 Executor 这个线程池中获取一个线程,将反序列化好的任务中的算子作用在 RDD 对应的分区上
stage的提交及执行

第二部分:SparkContext的初始化

  1. 处理用户的 jar 或者资源文件,和日志处理相关:isEventLogEnabled、eventLogDir、eventLogCodec的初始化
  2. 初始化异步监听 bus:LiveListenerBus,监听 Spark 事件,用于 SparkUI 的跟踪管理
  3. 初始化 Spark 运行环境相关变量,createSparkEnv方法:包括conf、运行模式、listenerBus、numDriverCores等
  4. 创建executorEnvs,是map类型,用于接受反向注册的executor信息
  5. 需要先启动 HeartbeatReceiver:setupEndpoint 方法
  6. 创建TaskSceduler,SchedulerBackend,DAGScheduler ;TaskScheduler在HeartbeatReceiver上进行注册,SchedulerBackend会在TaskScheduler上注册

第三部分:stage的提交

  1. 生成stageSet,提交stage到 waiting stage 和一个 running stage两个hashset中
  2. running stage 提交后,分析 stage 里 Task 的类型,生成一个 Task 描述(resultTask和 ShuffleMapTask),即 TaskSet
  3. 调用 TaskScheduler.submitTask(taskSet, …) 方法,把 Task 描述提交给 TaskScheduler 。
  4. TaskScheduler 依据资源量和触发分配条件,会为这个 TaskSet 分配资源并触发执行(SchedulerBackend)。
  5. DAGScheduler 提交 job 后,异步返回 JobWaiter 对象,能够返回 job 运行状态,能够 cancel job, 执行成功后会处理并返回结果

第四部分:其他

  1. TaskScheduler:
    维护 task 和 executor 对应关系,executor 和物理资源对应关系,在排队的 task 和正在跑的 task。维护内部一个任务队列,根据 FIFO 或 Fair 策略,调度任务。
  2. SchedulerBackend :
    SchedulerBackend 把自己手头上的可用资源交给 TaskScheduler, TaskScheduler 根据调度策略分配给排队的任务,返回一批可执行的任务描 述,SchedulerBackend 负责 launchTask,即最终把task塞到了executor模型上,executor 里 的线程池会执行 task的run()
  3. resultTask和 ShuffleMapTask:即最后输出和中间过程两种task
    设想有: Stage1 ----shuffle--------> Stage2 -----shuffle------> Stage3
    Stage3就是一个ResultTask, 因为是最终的action的执行;
    Stage2既是1个shuffle的数据读取者, 又是1个shuffle的数据输出者, 一个task同时兼具上述两种角色;
    Stage1就是一个ShuffleMapTask
  4. Accumulator:计数器
    A. 如果 task 是 ResultTask,在 job 里为该 task 置为 true,job finish 总数加一。如果 task 执行成功,对应的 stage 里减去这个 task,
    B. 如果 task 是 ShuffleMapTask,在 stage 里加上一个 output location,里面是一个 MapStatus 类。MapStatus 是 ShuffleMapTask 执行完成的返回,包含 location 信息和 block size( 使下一个stage能够读取上一个stage的结果)。

总感觉需要一张图来描述这一过程,但是我看了好几个图都感觉没法把这些过程完美的展现出来,感觉老李的这个图还是比较好的,虽然只有一个大概的流程
Spark作业提交原理图

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值