问题背景
最近注意到自己负责的一个任务调度集群碰到了计算资源业务线分配不均的问题(即业务线资源隔离没有做好):
- 在任务高峰期,调度系统会将计算资源偏向分配给(执行耗时比较长的)大任务,而(执行耗时比较短的)小任务却分到较少的计算资源。
- 当某一个业务线的任务都是大任务时,就会出现大部分计算资源都分配到该业务线,而其他业务线只分配到较少的计算资源。
阅读该系统调度相关代码稍加分析就明白了为什么会出现这种情况,在分析之前先讲一下这个任务调度系统工作机制:
- 该系统为master-slave模式,即有一个中心调度节点,多个工作节点。
- 工作节点会不停的尝试请求中心调度节点获取任务并执行,循环往复。
- 当工作节点请求调度节点获取任务时,调度节点会选择一条业务线,并将该业务线的任务返回给工作节点。
问题分析
现在问题就出现在调度节点选择业务线的算法上,目前的算法是:
- 各业务线提前配置好资源上下限,根据任务堆积情况进行自动扩缩,即每条业务线分配的资源是实时计算的。
- 选择业务线则是根据业务线实时配置的计算资源 / 所有业务线实时配置的资源之和 得到一个权重比例,然后根据该权重比例进行选择业务线。权重比例大(即该业务线配置的资源在所有业务线资源之和中所占比例大),被选中的概率就大。
这个算法粗略一看没什么问题,但是仔细分析一下这里忽略了一个关键因素:没有考虑任务执行耗时,默认任务执行耗时都一样。
这样会造成大任务占用了大部分的计算资源(即工作节点),这里简单描述一下:
- 这里有A、B2条业务线,分别配置了5个计算资源(总共10个计算资源):可以计算得出每条业务线中的任务被执行的概率是50%。
- 其中业务线A中有100大任务,业务线B有200个小任务。假设大任务执行需要20s,小任务执行需要10s。那么正常情况业务线A总共需要(100 * 20) 2000s计算时间才能执行完,业务线B也需要(200 * 10)2000s计算时间执行完,同时在(2000s * 2 / 10)400s后执行完成
- 实际情况是:
调度轮次 | 第1次 | 第2次 | 第3次 | 第4次 | 第5次 | 第6次 | 第N次 |
---|---|---|---|---|---|---|---|
选择的业务线 | A | B | A | B | A | B | |
业务线A剩余任务 | 99 | 99 | 98 | 98 | 97 | 97 | 100 - N/2 |
业务线B剩余任务 | 200 | 199 | 199 | 198 | 198 | 197 | 200 - N/2 |
大家发现端倪没有,虽然在选择任务线的逻辑上是公平的、符合预期的,但是任务本身是不公平的(任务执行耗时有长有短),这就会造成大任务多的业务线实际上分配了比预期多得多的计算资源。
思考
到了这里,心里出现了一些疑问:
- 调度系统存在的意义是什么?
- 任务怎么调度才符合预期?
对于第一个问题,我给出一些我的见解:任务调度系统存在的意义是解决任务与计算资源之间的矛盾。如果计算资源足够多,多到每一个任务都能够立即得到执行,那么调度系统就没有存在的意义了。
第二个问题,任务怎么调度才符合预期。
还记得上文我提到的业务线提前配置好资源上下限吗?
对,这个很关键。业务线配置的是资源的上下限,业务线只关心资源,只要分配给业务线的资源符合预期就行,不用关心这一次任务到底调度业务线A还是业务线B的任务。
理清楚了第二个问题,那么之前的调度算法问题就很明显了,计算权重时应该把计算资源的因素考虑进去。
计算资源的视角
在任务调度系统中,看待资源,我觉得有两种视角:
- 机器视角
- 计算时间视角
机器视角
这个很好理解,符合自然直觉。把物理机器当成一种计算资源,这个物理机器分配给业务线A就是业务线A的计算资源,必须优先执行业务线A的任务。
那么在调度任务时逻辑就非常简单了,这台物理机器尝试从调度节点获取任务时,应该优先获取业务线A的任务,只有当业务线A没有任务时才能借给其他业务线执行任务。
在机器视角下,业务线资源分配逻辑被前置到了物理机器启动环节,即在机器启动时就要确定好归属于哪条业务线。
在机器视角下,业务线资源隔离、分配变得很简单了,但是也存在不小的问题,至少在我这个(动态扩缩容)场景下不太适用:因为我们的调度系统每分钟都要动态计算每条业务线的目标资源数量,很有可能因为资源不足导致分配给某条业务线的机器一直起不来,就会导致该业务线没有计算资源执行任务。
在实际的操作过程中,我选择了从计算时间视角看待计算资源,来解决我碰到的问题。
计算时间视角
在机器视角中,把物理机器看成计算资源;在计算时间视角中,把物理机器的计算时间抽象成计算资源。
怎么理解计算时间是一种计算资源呢?可以参考现在计算机中CPU的调度逻辑,把CPU计算资源按照时间进行分片,按照一定的算法将计算时间分配给不同的进程,达到多个进程同时运行的效果。
在计算时间视角下,不管底层机器有多少台,始终按照业务线实时配置的计算资源 / 所有业务线实时配置的资源之和 得到一个权重比例去分配计算资源。
具体做法是:
- 业务线实时配置的计算资源 / 所有业务线实时配置的资源之和 得到一个权重比例,称之为P吧。
- 统计本轮资源调度中,所有业务线已使用的计算时间之和,称之为T吧。
- 比较本轮资源调度中,某业务线已使用的计算时间是否大于 T * P:若大于,则说明该业务线的计算时间已经使用完,不能再参与本次任务调度了;反之则正常参与任务调度计算。
- 计算业务线实时配置的计算资源 / 剩下业务线实时配置的资源之和 得到一个权重比例,按照该比例进行任务调度
通过计算时间的视角去分配计算资源,能够屏蔽底层机器状态,比如资源不够机器起不来、机器扩缩容等没有达到目标机器数量的情况。
通过计算时间的视角抽象计算资源也有弊端:如果底层机器计算能力差异很大的时候仍然会干扰资源分配的准确性。