Erlo

YARN——正确理解容量调度的capacity参数

2021-06-22 04:00:23 发布   281 浏览  
页面报错/反馈
收藏 点赞

容量调度器中,配得最多的应该就是capacity和maximum-capacity了,一个是当前队列的资源容量,一个是队列可使用的最大容量。多个队列的容量之和为100。


maximum-capacity这个参数还好理解,即队列可使用资源的上限。

假如有多个队列,每个队列都将maximum-capacity的值设置成与capacity一样,意味着每个队列只能使用固定大小的资源,不能超额使用其他队列空闲资源,这样,也就可能出现资源浪费或利用率低的情况。


因此,通常该值会设置成比capacity大。例如都设置为100,也就是每个队列最大都可以使用集群的全部资源。

但既然最大都可以使用集群的全部资源,那么capacity参数的作用和意义到底是什么,该参数又是如何限制用户资源使用的。


查看了官方文档,网上也看了不少文章,始终觉得没有讲透capacity这个参数的意义,索性直接撸源码。


结合源码,并对照日志,确认了几个关键点后,对自己的结论很是自信,立马邮件同步给组内的小伙伴。


队列的capacity参数是单个用户在该队列中所能使用资源的上限。


由于允许多个不同的用户向同一个队列提交任务,因此多个用户的不同任务的资源叠加起来可以超过capacity,但是不能超过maximum-capacity。


然而,没过多久,就收到了同事的答复邮件,并附带如下图示:队列配置10%的资源,用户提交了一个任务,使用的资源远超10%!



收到邮件,瞬间觉得脸已被打肿,但是之前研究相关源码,确定应该是会限制的啊,难道是哪个细节没注意到,代码走了其他分支?


带着疑问再次走读相关代码,并进行一系列测试,发现该现象是可以解释的,之前给出的结论也仍旧还是成立的。


当前集群的总资源为12GB,队列容量设置为10%,因此该队列上,单个用户理论上资源使用的上限为:

12 * 1024 * 0.1 = 1228.8MB

注:该队列的父队列为root,如果父队列不是root,则需要继续乘父队列的容量百分比。


由于配置的集群资源分配最小单位为1024MB,因此需要向上取整,即2048MB。也就是单个用户使用的资源上限为2048MB。


当spark任务的driver启动时(申请的资源为2048MB),当前队列中,该用户已使用的资源为0,未超过上限,因此可以为其分配资源,即driver可以成功启动。


driver启动后继续申请启动两个executor,每个executor申请分配2048MB。yarn调度时,发现该用户当前已使用资源为2048MB(为driver分配的资源),仍旧未超过上限,因此继续为一个executor分配了资源。但轮到第二个executor时,该用户当前已使用的资源变为了4096MB,超过了上限,因此没有为该executor分配资源。


也就是说:虽然队列容量配置的是10%,但并不是严格按照10%来限制,即允许超额使用。只要用户当前已使用资源没有超过上限,就可以继续分配(即便分配后会超过上限);但一旦当前已使用的资源超过了上限时,则不能再继续分配资源。


为了验证上面的结论,再进行如下测试:队列的容量仍旧配置为10%,同时将AM资源使用限制调高(maximum-am-resource-percent),防止因AM资源受限出现干扰。


先提交一个spark任务,情况和上面的情况一样,再次提交一个任务时,第二个任务始终处于ACCEPT状态,spark任务的driver都没有进行资源分配。



同时,从界面上可以看到任务的诊断信息为:超过用户资源使用上限。



在这个基础之上,切换用户,再提交一个spark任务,发现任务可以正常运行,如下图所示:



将该队列的AM资源使用限制调回到原来的值,再来进行测试,第二个任务同样处于ACCEPT状态,但界面上看到的信息则不同,提示为:超过用户AM最大使用资源



到这里,也就验证了之前的结论是正确的了。


将上面的测试过程,相关截图,以及结论总结进行了汇总,然后邮件进行了回复,以为可以告一段落了。但是,过了一会,再次收到了邮件,回复如下:


将队列的容量设置为5%,那么理论上该队列单个用户的最大使用资源为:

12 * 1024 * 0.05 = 614.4MB

向上取整为1024MB,按你的结论,提交的任务应该都无法分配资源,处于ACCEPT状态才对,然而还是进行了资源的分配,如下图所示:



看到邮件后,心情很平淡,因为之前的研究过程中,已经发现了这个问题,直接贴一段代码说明:



也就是说,只要当前队列中没有任务在运行,提交任务时,即便是超过了用户可使用资源的上限,仍旧会进行资源的分配,保证有一个任务可以运行


另外,从上面的图中,还可以看出一点,该任务只分配了2048MB,也就是driver的资源,而driver申请启动的executor均未分配到任何资源,因为当前已使用资源已经超过了上限。


【总结】


队列的capacity参数是作用于单个用户的资源使用上限,真正调度分配时只要用户已使用资源未超过上限,就可以继续分配(分配后可以超过上限)。


当然决定用户资源使用上限的还有其他参数,例如user-limit-factor,minimum-user-limit-percent等,后续文章再单独说明。


另外,整个讨论过程下来,体会到源码是不会说谎的,看源码的同时还是要多动手测试验证,才能真正做到正确理解。


好了,本文就讲到这里,原创不易,点赞,在看,分享是最好的支持, 谢谢~


本文分享自微信公众号 - hncscwc(gh_383bc7486c1a)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

登录查看全部

参与评论

评论留言

还没有评论留言,赶紧来抢楼吧~~

手机查看

返回顶部

给这篇文章打个标签吧~

棒极了 糟糕透顶 好文章 PHP JAVA JS 小程序 Python SEO MySql 确认