Spark原理性笔记
一、调度系统
1、Spark调度系统简述
Spark调度系统的核心职责:先将构建好的DAG拆分成分布式任务(划分成不同Stages以及创建内部Tasks),根据集群的资源情况,按照调度规则按照一定顺序将分布式任务分发到执行器中执行。
2、Spark调度系统的组件以及作用
Spark调度系统的组件可以分为以下三个:
- DAGScheduler
- SchedulerBackend
- TaskScheduler
2-1、DAGScheduler
DAGScheduler的主要职责有两个,一个是将DAG拆分成不同的Stages(根据是否存在shuffle),另外一个是在Stages内创建Tasks。
2-2、SchedulerBackend
SchedulerBackend是资源调度器的封装和抽象,主要职责有两个,一个是管理集群的资源,向集群提供硬件资源情况,另外一个是将分布式任务分发到执行器Executor中。
这里,管理集群资源,提供资源情况的原理是:
- SchedulerBackend为了支持各种调度模式,比如Standalone、Yarn等都提供了相应的实现类,通过指定MasterUrl使用不同的调度实现类。
- 内部维护一个硬件资源映射字典:ExecutorDataMap,key是标示节点Executor的字符串,value是ExecutorData数据结构对象,其中封装了节点Executor的硬件信息,比如可用CPU核数、总共CPU核数、可用内存大小、总共内存大小、RPC地址等。
- 对外提供资源时,查看ExecutorDataMap,将可以提供的资源以WorkOffer的形式提供,WorkOffer封装了ExecutorID、CPU可用核数等资源信息。
这里,将分布式任务分发到执行器Executor的原理是:
- 按照顺序将task分发到对应其要去的Executor
2-3、TaskScheduler
TaskScheduler的主要作用是任务调度的规则和策略,也就是决定优先调度什么任务组(Stage)或任务(tasks),主要分为Stage之间的调度和Stage内的tasks的调度。
Stage之间的调度:如果Stages之间存在依赖关系,那么按照依赖关系调度即可。如果Stages之间不存在依赖关系,那么TaskScheduler主要提供了两种调度规则,FIFO(先到先得)和 FAIR(公平调度)。FIFO就是按照Stages的创建时间进行调度,这种方式是最简单的方式。FAIR是按照设置的调度优先级进行调度,Spark允许设置不同的调度池(拥有不同的优先级),在开发时可以关联作业和调度池,使得作业的调度优先级符合开发者意愿,FAIR的调度池的优先级可以在fairscheduler.xml文件中设置(调度池以及优先级从这个文件读取)。
Stage内的tasks的调度:Stage内部的调度,依据的是数据本地性级别,主要分为四个级别:Process local >Node local >Rack local > Any,也就是进程本地性>节点本地性>机架本地性>跨机架本地性。当TaskScheduler收到SchedulerBackend的WorkOffer时,会挑选那些满足本地性级别的任务,也就是先调度符合Process local的、然后是Node local、Rack local、Any。如何知道哪些任务符合这些筛选条件呢?其实,在创建这些tasks时,就会为他们指定本地性级别信息,本地性级别信息会记录执行他需要到的节点信息甚至是Executor进程ID,这样在挑选符合本地性级别任务时,可以指向性的挑选。如果进程本地性不满足,就看节点本地性是不是满足,不然看机架本地性是不是满足,不然就跨机架本地性。也就是说,在提供的Workoffer中,每个task都有其对应的本地性级别。
举个例子,一批WorkOffer过来,task1的进程本地性是进程X,同时这一批WorkOffer中有进程X,那么这个task的调度就是Process local (进程本地性)。此时task2的进程本地性是进程Y,但是这一批WorkOffer中没有进程Y,但是task2想去的进程在节点2上,这一批WorkOffer中有节点2,那么退而求其次,task2的调度级别就是Node local(节点本地性),以此类推。
这里,task的本地性优先级的目的是减少数据的网络传输,让数据尽量呆在本地,由本地的task来使用。
在TaskScheduler甄选出本批WorkOffer符合的tasks后,将任务序列化,SchedulerBackend根据ExecutorData记录RPC地址和主机地址将序列化的任务发送到目标主机的Executor中,然后Executor的线程池启动线程并发执行task。