Spark 调度系统的工作流程包含如下 5 个步骤:
- 将 DAG 拆分为不同的运行阶段 Stages;
- 创建分布式任务 Tasks 和任务组 TaskSet;
- 获取集群内可用的硬件资源情况;
- 按照调度规则决定优先调度哪些任务 / 组;
依序将分布式任务分发到执行器 Executor。
image.png
调度系统中的核心组件有哪些?
1. DAGScheduler(需求端,创建的tasks就是需求)
职责
1.把用户 DAG 拆分为 Stages;
2.在 Stage 内创建计算任务 Tasks2. SchedulerBackend(资源供给端,Executors资源情况)
职责:
资源调度器的封装与抽象(SchedulerBackend是资源调度的接口,对接不同资源调度模式需要不同的资源调度实现)
不同资源调度模式对应的实现类(local,Standalone,yarn-cluster,yarn-client等)CoarseGrainedSchedulerBackend 是SchedulerBackend 的一个粗粒度资源调度实现
对内(Executors资源情况)
SchedulerBackend 用 ExecutorData 对 Executor 进行资源画像;
用一个叫做 ExecutorDataMap 的数据结构,来记录每一个计算节点中 Executors 的资源状态。ExecutorDataMap 是一种 HashMap,它的 Key 是标记 Executor 的字符串,Value 是一种叫做 ExecutorData 的数据结构,ExecutorData 用于封装 Executor 的资源状态,如 RPC 地址、主机地址、可用 CPU 核数和满配 CPU 核数等等,它相当于是对 Executor 做的“资源画像”对外(tasks对资源的需求)
SchedulerBackend 以 WorkerOffer 为粒度提供计算资源,WorkerOffer 封装了 Executor ID、主机地址和 CPU 核数,用来表示一份可用于调度任务的空闲资源。
3.TaskScheduler(中介,将需求与资源按规则分配)
职责:
基于既定的规则与策略达成供需双方的匹配与撮合。
也就是将tasks 与 WorkerOffer按照规则与策略进行匹配调度优先级类型
不同 Stages 之间
Stages 之间的任务调度,TaskScheduler 提供了 2 种调度模式,分别是 FIFO(先到先得)和 FAIR(公平调度)
FIFO(先到先得)
Stages 按照被创建的时间顺序来依次消费可用计算资源
FAIR(公平调度)
哪个 Stages 优先被调度,取决于用户在配置文件 fairscheduler.xml 中的定义。
在配置文件中,Spark 允许用户定义不同的调度池,每个调度池可以指定不同的调度优先级,用户在开发过程中可以关联不同作业与调度池的对应关系,这样不同 Stages 的调度就直接和开发者的意愿挂钩,也就能享受不同的优先级待遇同 Stages 内不同任务
当 TaskScheduler 接收到来自 SchedulerBackend 的 WorkerOffer 后,TaskScheduler 会优先挑选那些满足本地性级别要求的任务进行分发
本地性级别
Process local < Node local < Rack local < Any
从左到右分别是进程本地性、节点本地性、机架本地性和跨机架本地性。从左到右,计算任务访问所需数据的效率越来越差本地性级别如何确定
根据任务依赖的数据集分片所在的位置信息
本地性级别何时确定
DAGScheduler 划分 Stages、创建分布式任务的过程中,会为每一个任务指定本地性级别
任务调度流程图
归纳
1.核心职责
先将用户构建的 DAG 转化为分布式任务,结合分布式集群资源的可用性,基于调度规则依序把分布式任务分发到执行器 Executors;
2.核心原则
尽可能地让数据呆在原地、保持不动,同时尽可能地把>>>承载计算任务的代码分发到离数据最近的地方(Executors 或计算节点),从而最大限度地降低分布式系统中的网络开销。