1. 消息通信原理
- Spark启动消息通信:启动过程主要是进行Master与Worker之间的通信
- Worker节点向Master发送注册消息
- Master处理完后,返回注册成功(失败)消息
- 若成功,则Worker定时发送心跳消息给Master
- Spark运行时消息通信:
- 应用程序的SparkContext向Master发送应用注册消息
- Master给该应用分配Executor
- Executor向SparkContext发送注册成功消息
- SparkContext的RDD触发行动操作后,将创建RDD的DAG,通过DAGScheduler进行划分Stage,并将Stage转化为TaskSet
- 由TaskScheduler向注册的Executor发送执行消息,Excutor收到任务消息后启动并运行
- 当所有任务运行时,由Driver处理结果并回收资源
Spark能够有效进行调度的根本原因是对任务划分DAG和容错
2. 划分DAG和容错
- 作业Job:RDD中由action操作生成的一个或多个调度阶段
- 调度阶段Stage:每个Job会因为RDD之间的依赖关系拆分多组任务集合(称为调度阶段, 也叫作TaskSet任务集)调度阶段由DAGScheduler来划分,调度阶段有Shuffle Map Stage和Result Stage
- 任务Task:Spark实际执行应用的最小单元,分发到Executor上的工作任务
- DAGScheduler:面向调度阶段的任务调度器,负责接收Spark应用提交的作业、根据RDD的依赖关系划分调度阶段、提交调度阶段给TaskScheduler
- TaskScheduler:面向任务的调度器,接受DAGScheduler提交的调度阶段、分发任务到Work节点,由Work节点的Executor来运行任务
3. 作业执行原理:
提交作业、划分调度阶段、提交调度阶段、提交任务、执行任务、获取执行结果
- 触发SparkContext的runJob方法提交作业
- SparkContext的runJob方法进入DAGScheduler类的runJob方法,DAGScheduler提交作业、划分阶段
- 划分调度阶段:当某个RDD操作是Shuffle时,以该Shuffle操作为界限分为两个调度阶段
- 提交调度阶段:DAGScheduler
- 提交任务:根据调度阶段Partition个数拆分对应个数任务,组成任务集提交到TaskScheduler进行处理(一个任务集处理逻辑完全一样,不同的是对应处理的数据)。TaskScheduler收到任务集猴,每个任务均分配运行代码、数据分片、处理资源等。调用Worker上的Executor来执行任务
- 执行任务:对于ShuffleMapTask,最终返回DAGScheduler的一个MapStatus对象,保存了存储信息,将会成为下一阶段的任务需要获得的输入数据时的依据;对于ResultTask,返回的是计算结果。
- 获取计算结果:对于Executor的计算结果,根据结果的大小有不同的策略
4. 调度算法:
- 应用程序之间
- 分配应用程序资源策略:
- 应用程序运行在尽可能多的Worker上:不仅能充分使用集群资源,而且有利于数据处理的本地性
- 应用程序运行在尽可能少的Worker上:适合CPU密集型(计算密集型)而内存使用较少的场景
- 分配应用程序资源策略:
- 作业及调度阶段之间
- 多个作业之间的调度:
- FIFO调度
- FAIR模式,配置Job执行的优先
- 任务之间的调度:
- 让任务运行在数据本地性优先级高的节点上,甚至可以为此等待一定的时间
- 多个作业之间的调度: