我们每天都在谈论分布式架构,也有朋友经常问我分布式架构到底是个什么的架构。其实简单来说就是,分布式系统架构就是将多个服务器资源统一管理起来,然后挑选合适的服务器去处理用户的请求或者指定的任务。当然分布式系统技术肯定不是这一篇能讲清楚的,前面也讲了两篇了,忘记了的可以回顾下(不好意思,懂分布式事务的你真的很了不起,下篇,面试是不是经常被问到分布式系统核心问题,这一次没人难倒你)我也会一直讲这方面技术的。
那究竟什么样的服务器是比较合适的呢,有没有什么衡量标呢,其实衡量一个服务器是否是合适的是会受到很多条件约束的,比如,我们有很多业务场景中,是有优先级的,那么我们在执行多任务时,就需要保证优先级高的任务先执行。
为用户提交的任务选择合适的合适的服务器的这一过程,在分布式领域中就叫做“调度”。在分布式系统架构中,调度器起着至关重要的作用,是非常重要的一个组件,它通过各种调度策略来完成我们各种任务的调度工作。你想想看如果没有这么个组件,那我们的分布式系统岂不是非常混乱,好比现在复杂路口指挥交通的交警叔叔,他通过自己的调度策略来完成车辆行人的调度工作。
当然,不同的分布式架构中调度器的原理可能会不相同,在我们开发中接触最多的最常见的就是单体调度器,即调度匹配任务和分布式系统中的空闲资源,直白的解释就是说调度器管理着任务和分布式中的所有资源。
下面我们就来具体学习下分布式架构中的单体调度器。
01
什么是单体调度?
分布式系统中的单体调度是指,在集群中有一个节点运行着调度的程序,同时具备访问其他节点的权限,它能够搜集各个节点的资源信息以及状态等信息,然后统一进行管理。根据用户下发的任务与资源的需求进行匹配,最终匹配到的结果即为执行任务的节点。
可见,单体调度是一个全局的概念,它拥有全局的资源信息和全局任务,像 Google Borg、Kubernetes 等集群管理系统采用的均是单体调度。我们来看看单体调度的架构图:
如上图所示,master节点上运行着调度程序,负责资源管理,任务和资源匹配。右边的node1,node2...node n就是主从架构中的slave节点,这种架构前面已经讲了很多了,忘记就回去看看。
slave节点将自身的状态state上报给master的 Cluster State模块,Cluster State模块用来管理集群中节点资源等状态,然后将资源等状态传送给 Scheduling Logic 模块,以便任务tasks与资源匹配,最后根据匹配结果将tasks发送到它匹配的节点上。
02
单调调度设计
在集群管理中,单体调度模块即为调度器,即使用中心化的方式管理资源和任务调度。
在 Borg 和 Kubernetes 这两个集群管理系统中,Scheduler 是它们的核心。而 Kubernetes 又是 Borg 的开源版本。所以接下来,我就以 Borg 为例,来讲述它的调度器是如何设计的,才能保证在上万台机器规模的集群上,运行来自几千个不同应用的几十万个作业。
03
Brog调度设计
我们知道调度的核心就是为作业或者任务选择合适的资源匹配,首先我们先来看看Brog的系统架构图。
- Scheduler主要负责任务的调度工作
- 用户提交作业给BrogMaster后,BrogMaster会将该作业保存到Paxos仓库中。
- 然后将作业中的所有任务添加到等待队列中
- 调度器异步扫描等待队列,将任务分配到资源匹配的计算节点上。
调度器在扫描队列时,按照任务的优先级从高到低进行选择,同优先级的任务则以轮询的方式处理,以保证用户间的公平,并避免队首的大型作业阻塞队列。
那究竟它是怎么去调度的呢?接下来我们就来看看Brog核心内容,也就是调度算法。
04
Brog 调度算法
Brog 调度算法的核心思想则为“筛选可行,评分取优”,具体包括两个阶段
- 可行性检查,首先找到可以运行任务的机器。
- 评分,从可行的机器当中挑选出合适的机器。
在可行性检查阶段,调度器会找到一组满足任务约束且有足够可用资源的机器。比如,现在有一个任务 A ,其中能部署的节点是节点 1、节点 3 和节点 5,并且任务资源需求为 0.8个 CPU、6MB 内存。根据任务 A 的约束条件,可以先筛选出节点 1、节点 3 和节点 5,然后根据任务 A 的资源需求,再从这 3 个节点中寻找满足任务资源需求的节点。
在评分阶段,Brog 会根据一个评分机制,对可行性检查阶段筛选出来的机器进行打分,从而选出最合适的执行机器。
通过上面我们知道,挑选可行机器倒是很容易,但是通过打分该怎么打呢,是一个这么样的评分算法呢,当然啦这个评分算法可以根据自己任务或者机器相关资源进行定制相关的评分算法的。
其中,在我们分布式系统中最常见的评分算法就是“最差匹配”和“最佳匹配”两种。
Borg 起初使用修改过的 E-PVM 算法来评分,该算法的核心是将任务尽量分散到不同的机器上。该算法的问题在于,它会导致每个机器都有少量的无法使用的剩余资源,因此有时称其为“最差匹配”(worst fit)。
比如,现在有两个机器,机器 A 的空闲资源为 1 个 CPU 和 1G 内存、机器 B 的空闲资源为 0.8 个 CPU 和 1.2G 内存;同时有两个任务,Task1 的资源需求为 0.4 个 CPU 和 0.3G 内存、Task2 的资源需求为 0.3CPU 和 0.5G 内存。按照最差匹配算法思想,Task1 和 Task2 会分别分配到机器 A 和机器 B 上,导致机器 A 和机器 B 都存在一些资源碎片,可能无法再运行其他 Task。
与之相反的是“最佳匹配”(best fit),即把机器上的任务塞得越满越好。这样就可以“空”出一些没有用户作业的机器(它们仍运行存储服务),来直接放置大型任务。
比如,在上面的例子中,按照最佳匹配算法的思想,Task1 和 Task2 会被一起部署到机器 A 或机器 B 上,这样未被部署的机器就可以用于执行其他大型任务了。
但是,如果用户或 Borg 错误估计了资源需求,紧凑的装箱操作会对性能造成巨大的影响。比如,用户估计它的任务 A 需要 0.5 个 CPU 和 1G 内存,运行该任务的服务器上由于部署了其他任务,现在还剩 0.2 个 CPU 和 1.5G 内存,但用户的任务 A 突发峰值时(比如电商抢购),需要 1 个 CPU 和 3G 内存,很明显,初始资源估计错误,此时服务器资源不满足峰值需求,导致任务 A 不能正常运行。
所以说,最佳匹配策略不利于有突发负载的应用,而且对申请少量 CPU 的批处理作业也不友好,因为这些作业申请少量 CPU 本来就是为了更快速地被调度执行,并可以使用碎片资源。还有一个问题,这种策略有点类似“把所有鸡蛋放到一个篮子里面”,当这台服务器故障后,运行在这台服务器上的作业都会故障,对业务造成较大的影响。
因此,这两个评分算法各有利弊。在实践过程中,我们往往会根据实际情况来选择更适宜的评分算法。比如,对于资源比较紧缺,且业务流量比较规律,基本不会出现突发情况的场景,可以选择最佳匹配算法;如果资源比较丰富,且业务流量会经常出现突发情况的场景,可以选择最差匹配算法。
当然有很多调度框架是支持用户根据自己的场景自定义调度策略的,比如优先级策略、亲和性策略、反亲和性策略等。
05
多个集群 / 数据中心如何实现单体调度呢?
上面我们已经清楚了单体调度,其实是针对一个集群或一个数据中心的,那么多个集群或多个数据中心,能不能基于单体调度实现呢?
肯定是可以的,这就是集群联邦的概念了。
所谓集群联邦,就是将多个集群联合起来工作,核心思想是增加一个控制中心,由它提供统一对外接口,多个集群的 Master 向这个控制中心进行注册,控制中心会管理所有注册集群的状态和资源信息,控制中心接收到任务后会根据任务和集群信息进行调度匹配,选择到合适的集群后,将任务发送给相应的集群去执行。
总结,今天我们学习了分布式系统架构的单体调度,并且以Brog为例讲述了单体调度器的架构的设计和调度算法,虽然它可能有单点瓶颈问题,但是因为它具有全局的掌控能力,调度算法可以自定义等,因此广受公司使用,像Google,阿里,腾讯等公司都有使用。如果今天的内容能帮助你,恰好你又喜欢就关注我,我会一直分享业内实战架构知识,谢谢。
下一篇预告:讲讲分布式另外一种调度的方案
关于架构师修炼
本号旨在分享一线互联网各种技术架构解决方案,分布式以及高并发等相关专题,同时会将作者的学习总结进行整理并分享。
更多技术专题,敬请期待