一、任务调度和资源调度的区别
1.任务调度是通过DAGScheduler、TaskScheduler、SchedulerBackend等进行的作业调度
2.资源调度是指应用程序如何获得资源
3.任务调度是在资源调度的基础上进行的,没有资源就没有任务
二、资源调度原理
1.因为Master负责资源管理和调度,所以资源调度的方法shedule位于Master.scala这个类中,当注册程序或者资源发生改变时都会导致schedule的调用,例如注册程序的时候
2.Schedule调用的时机:每次有新的应用程序提交或者资源状况或者集群资源状况发生改变的时候,包括Executor增加或者减少、worker增加或者减少。
3.当前Master必须是alive的方式,才能进行资源的调度;如果不是alive的状态会直接返回。
4.使用Random.shuffle把Master中保留的集群中所有worker的信息随机打乱,其算法内部是循环随机交换
5.判断所有worker中那些事alive级别的worker,alive才能够参与资源的分配工作。
6.当SparkSubmit指定Driver在Cluster模式的情况下,此时Driver会加入waitingDriver等待列表中,在每个DriverInfo的DriverDescription中有要启动Driver时候对worker的内存及Cores的要求等内容。
在符资源要求的情况下采用随机打乱后的一个worker来启动Driver。
Master发指令给worker,让远程的worker启动Driver。
7.先启动Driver才会发生后续的一切资源调度的模式
8.Spark默认为应用程序启动Executor的方式是FIFO的方式,也就是说所有提交的应用程序都是放在调度的等待队列中的,先进先出,只有满足了前面应用程序的资源分配的基础上才能够满足下一个应用程序资源的分配。
9.为应用程序具体分配Executor之前要判断应用程序是否还需要分配Core,如果不需要则不会为应用程序分配Executor。
10.具体分配Executor之前要对要求worker必须是alive的状态且必须满足Application每个Executor的内存和Cores的要求,并且在此基础上进行排序产生计算资源由大到小的usableWorkers数据结构。
在FIFO的情况下默认是spreadOutApps来让应用程序尽可能多的运行在所有的Node上:
11.为应用程序分配Executors有两种方式:
(1)尽可能在集群中的所有worker上分配Executor,这种方式往往会带来潜在的更好的数据本地性(此时没有考虑数据本地性,只是为了更好的并发)
(2)
12.具体在集群上分配Cores的时候会尽可能的满足我们的要求
13.如果是每个worker下面只能够为当前的应用程序分配一个Executor的话,每次是分配一个Core!
14.准备具体要为当前应用程序分配的Executor信息后,Master要通过远程通信发指令给worker来具体启动ExecutorBackend进程
15.紧接着给Driver发送一个ExecutorAdded的信息。