昨天分享了分布式系统架构中的单体调度架构,并且详细的学习了相关调度算法(【分布式技术】分布式系统调度架构之单体调度,非掌握不可),虽然单体调度架构简单易用,但是它是落在中央处理器中的,所以也就有了单机瓶颈问题,这样对于一些多类型的服务就会受限。
正是因为单体调度的一些缺陷,所以聪明的程序员们就想出了一个两层调度来解决这种问题。
01
什么是两层调度?
两层调度就是将资源和任务分开调度,也就是说其中一层调度器做资源的管理和分配,另一层调度器则负责任务与资源的匹配。
资源的使用状态同时由中央调度器和第二层调度器管理,中央调度器从全局上进行资源的管理和分配,然后将资源分配到第二层调度器,接着第二层调度器就可以进行任务和资源的匹配。所以第二层是可以有多个调度器的,用来支持不同类型的任务,比如CPU密集型的以及io密集型的任务。
如上图所示,scheduler-1就是第一层中央调度器,主要负责收集和管理集群中资源信息;上面的scheduler-2就是第二层调度器
- scheduler-1将收集的集群资源信息发给scheduler-2。
- scheduler-2根据任务需要的资源情况和scheduler-1发送来的资源信息进行相关匹配和调度。
第一层调度器依然是一个经简化的中央调度器,一般是放在分布式集群管理系统中的,而第二层调度器是由我们各个应用程序框架完成。这两层调度器的职责分别是:
- 第一层调度器负责管理资源同时像框架去分配资源
- 第二层调度器接收第一层调度器分配来的资源,然后根据实际任务情况和收到的资源进行匹配
有哪些项目都采用了两层调度结构呢?这样的集群管理系统很多,其中较为典型就是 Apache Mesos 和 Hadoop YARN。下面我们就以Mesos为例,来一起学习下两层调度的架构设计以及它的分配算法。
02
两层调度的原理
Mesos 它是负责底层资源的管理和分配,但并不涉及存储以及任务调度的相关功能,所以,如果它要实现类似Brog 那样的资源和任务管理,还需要一个上层框架的配合。
Mesos 自己实现的调度器就是第一层调度,负责集群资源管理,接着将第二层任务调度工作交给我们的上层框架来完成,下面我们就来具体看看怎么实现的。
03
两层调度架构设计
通过上面我们已经知道了,其实以Mesos 为基础的分布式资源管理与调度框架应该包含两大部分,Mesos 资源管理集群和框架。
- 资源管理集群是由一个Master节点和多个Slave 节点而组成的一种集中式系统。其中每个集群有且仅有一个Master节点,负责管理slave节点,且对接框架。slave节点定期像 master 节点上报资源状态信息,并执行框架提交任务。
- 框架,运行在Mesos 上,是负责应用管理和调度的组件,比如 Hadoop,Spark,MPI等,不同的框架用来完成不同的任务。框架主要由调度器 Scheduler 和执行器 Executor 组件组成,scheduler可以从Master 节点获取资源信息,Executor 就在slave 节点上执行任务。
如上图所示,Mesos Master 有个调度器 Allocation Module 即为第一层调度。框架上负责任务的管理与调度的调度器,则为第二层调度。
通过上面我们应该很清楚了两层调度的工作模式了,那下面我们就来看看 Messos 两层调度的基本原理。
- 框架向 Mesos Master 中注册。
- Mesos Slave 节点向Master节点定期的上报自己的空闲资源信息。
- Mesos Master 中scheduler 进程收集所有节点的空闲资源信息,并以 Resource Offer的方式将空闲资源发送给注册来的框架。
- 框架的 Scheduler 接收到Mesos 发来的资源信息后,就进行任务调度和匹配,匹配成功后,就将匹配结果下发给 Mesos Master,然后mesos master 就会转发给对应节点的 executor 进行执行任务。
可见,Mesos 实现两层调度时,采用Resource Offer 机制来衔接第一层和第二层调度。Resouce Offer 是指 Mesos Master 主动将空闲资源以发放 Offer的方式发给框架,框架自身如果需要就使用,不需要就返回。
即通过 Resource Offer 机制,第一层调度将资源主动告知第二层调度,然后第二层调度进行具体的任务匹配,从而实现了任务调度与资源管理的分离,Mesos Master 通过资源分配算法决定给各个 Framework 提供多少资源,而 Framework 则决定接受哪些资源,以及哪些任务使用这些资源运行。这样一来,一个两层调度架构就实现了。
接下来我们就来看看第一层调度是怎么将空闲资源发给框架的,是通过什么算法实现的。
04
资源分配算法
Mesos 的资源分配算法解决的问题是,将当前空闲资源分配给哪些框架以及分配多少给框架,其最重要的资源分配有两种算法:
- 最大最小公平算法(Max- minFairness,MMF)
- 主导资源公平算法(Dominant Resource Fairness,DRF)。
1
最大最小公平算法
首先,我们看看最大最小公平算法,这是一种在兼顾公平的前提下,尽可能让更多人满意的资源分配算法。为什么这么说呢?因为这个算法有 3 个主要原则:
- 按照用户对资源需求量递增的顺序进行空闲资源分配;
- 不存在用户得到的资源超过自己需求的情况;
- 对于分配的资源不满足需求的用户,所获得的资源是相等的。
在执行资源分配时,最大最小公平算法按照上述 3 条原则进行多次迭代,每次迭代中资源均平均分配,如果还有剩余资源,就进入下一次迭代,一直到所有用户资源得到满足或集群资源分配完毕,迭代结束。
接下来,我们通过一个具体的例子来看看最大最小公平算法的资源分配流程吧。
假设,现在有总量为 100 的空闲资源,有 4 个用户 A、B、C、D 对该资源的需求量分别为(35,10,25,45),分配流程如下所示:
- 按照用户对资源的需求量升序排列,则 4 个用户的需求量为(B:10,C:25,A:35,D:45)。
- 平均分配空闲资源。资源空闲总量 100,除以用户数 4,则平均空闲资源量为 25;按照第一步中需求量分配后,用户资源需求量为(0,0,10,20),且用户 B 由于资源需求量小于 25,因此会剩余资源。此时空闲资源量为 15,资源需求人数为 2。
- 重复第二步,平均分配资源,15/2=7.5,即分别为用户 A 和 D 分配 7.5 份资源,此时用户资源需求量为(0,0,2.5,12.5),空闲资源量为 0,资源需求人数为 2。
- 所有资源已分配完,算法终止。
最大最小公平算法的执行流程,如下图所示。
如上案例,最大最小公平算法是由于所有资源全部分配完才终止的。至此,对于需求量为(10,25,35,45)的用户们来说,分配到的资源是(10,25,32.5,32.5)。这个算法的另外一个结束条件是,资源分配满足了所有用户的资源需求,即当没有用户有资源需求时,算法也会终止。
2
主导资源公平算法
最大最小公平算法采用了绝对公平的方式分配资源,会导致大量的资源浪费,比如用户需求量为 35 和 45 的用户 A 和用户 D,均分配了 32.5 的空闲资源,但由于资源不满足需求,这两个用户均无法使用。
而主导资源公平算法在考虑用户公平性的前提下,还考虑了用户对不同资源类型的需求,以尽可能地合理分配资源。也就是说,同样的资源量,主导资源公平算法可以尽可能地满足更多的用户。
在 Mesos 中,框架对资源的需求往往包括对 CPU、内存等多种类型资源的需求。针对多种资源的需求,主导资源公平算法首先计算已经分配给用户的每一种资源的占用率(Resource Share),比如已经分配的 CPU 占总资源量的多少,已经分配的内存占总资源量的多少。所有资源占用率中的最大值称作该用户的主导资源占用率,而主导资源占用率对应的资源就是用户的主导资源。
我们通过一个具体的案例,看看如何判断用户的主导资源吧。如下图所示,假设系统中的资源共包括 18 个 CPU 和 36 GB 内存,有两个 Framework(Framework A 和 Framework B)分别运行了两种任务,假设 Framework A 运行内存密集型任务,Framework B 运行 CPU 密集型任务,且每个任务所需要的资源量是一致的,分别是 <2 CPU, 8 GB> 和 <6 CPU, 2 GB>。
1,计算资源分配量。
假设 x 和 y 分别是 Framework A 和 Framework B 分配的任务数,那么 Framework A 消耗的资源为{2x CPU,8x GB},Framework B 消耗的资源数为{6y CPU,2y GB},分配给两个 Framework 的总资源量为(2x 6y)个 CPU 和(8x 2y)GB 内存。
2,确定主导资源。
对于 Framework A 来说,每个任务要消耗总 CPU 资源的 2/18,总内存资源的 8/36,所以 Framework A 的主导资源为内存;对于 Framework B 来说,每个任务要消耗总 CPU 资源的 6/18 和总内存资源的 2/36,因而 Framework B 的主导资源为 CPU。
3,DRF 算法的核心
是平衡所有用户的主导资源占用率,尽可能试图最大化所有用户中最小的主导资源占用率。通过求解下列公式,可以计算出 Framework A 和 Framework B 分配的任务数,并且要在满足公式的条件下,使得 x 和 y 越大越好。
代码语言:javascript复制2x 6y≤18
8x 2y≤36
8x/36=6y/18
通过求解可以得出:x=3,即 Framework A 可以运行 3 个任务;y=2,即 Framework B 可以运行 2 个任务。这样分配的话,每个 Framework 获取了相同比例的主导资源,即:A 获取了 2/3 的内存,B 获取了 2/3 的 CPU,从而在主导资源上体现了调度算法的公平性。
在实际任务分配过程中,主导资源率是根据已经分配给 Framework 的资源,占集群中总资源量的多少进行计算的,并且在每次分配过程中,会选择主导资源最小的 Framework 进行分配,也就是试图最大化所有用户中最小的主导资源占用率。
3
两种算法对比
- 最大最小公平算法适用于单一类型的资源分配场景
- 而主导资源公平算法适用于多种类型资源混合的场景。
- 最大最小公平算法从公平的角度出发,为每个用户分配不多于需求量的资源。
- 主导资源公平算法从任务出发,目的在于尽量充分利用资源使得能够执行的任务越多越好。
总结,今天我们学习了分布式架构系统的两层调度架构,是为了解决一些多类型的场景下单体调度所面临的单点瓶颈问题,并以Mesos 为例进行讲解了两层调度的架构设计以及它的两种资源分配算法,并给出了两者的比较和建议的使用场景,希望今天的内容多你有帮助,谢谢。