为了账号安全,请及时绑定邮箱和手机立即绑定

java的容器支持cpu

标签:
Java

之前一直很好奇,java是如何根据容器的外部设置的cpu限制来做自适应的。下面就跟随openjdk,看看系统是如何应对cgroup cpu设置的。
代码位置在jdk/src/hotspot/os/linux/cgroupSubsystem_linux.cpp的active_processor_count的方法。
目前cpu的设置,主要是3种使用方式,第一种是设置quota,第二种是设置share比率,第三种是设置cpu具体的核。以下就围绕着三种情况进行展开。
以下原来来自openjdk18

quota模式

  if (quota > -1 && period > 0) {
    quota_count = ceilf((float)quota / (float)period);
    log_trace(os, container)("CPU Quota count based on quota/period: %d", quota_count);
  }

在设置了quota和period。jdk就用quota/period作为cpu的核数。这里的处理是虚拟的核数。因为period的周期是可以调整的,是否真的用到了对应倍数的物理机核,这里其实是不确定的。

share模型

在share模式下,只是设置了竞争cpu的比率。竞争强跑满了,share才有限制,如果都跑不满,限制是不存在的。在这种情况下,就需要用户做一些自己系统的预判。第一个设置是UseContainerCpuShares,开启这个参数后,就会读取cpu.shares的配置值,然后和1024(默认值做倍数关系)

  if (share > -1) {
    share_count = ceilf((float)share / (float)PER_CPU_SHARES);
    log_trace(os, container)("CPU Share count based on shares: %d", share_count);
  }

这种就是模拟大家都跑满的场景。并且希望设置核数比率的时候,是按照默认值的倍数来进行设置。否者jdk拿到的核数是不对的。这里只是jdk自己的限制,cgroup并没有这么要求。
如果不开启UseContainerCpuShares,share就会用系统的核数。这里模拟的就是程序竞争不激烈的情况。

 cpu_count = limit_count = os::Linux::active_processor_count();

直接限制物理核

通过cgroup设置cpuset.cpus,可以固定使用具体某几个核。这种设置在系统函数中就会返回被限制后的。

 cpu_count = limit_count = os::Linux::active_processor_count();

混合模式

以上三种模式,是可以混合在一起设置的。我们来继续看看,当出现混合设置的时候,如何去做cpu个数的计算。
先处理share和quota
这里的share是开启了UseContainerCpuShares的情况,没开启的时候拿到的核数和设置了cpuset.cpus是同一个逻辑。同时引入了一个新的参数PreferContainerQuotaForCPUCount,这个参数开启了就会直接使用quota值。否则会根据share和quota谁的比较小来做判断。

   if (PreferContainerQuotaForCPUCount) {
      limit_count = quota_count;
    } else {
      limit_count = MIN2(quota_count, share_count);
    }

最后需要和cpuset.cpus的结果在做对比。这里注意的一点是,share不开启UseContainerCpuShares之后获取物理核的方法和cpuset.cpus是同一个,所以接下来的对比是包含了2中情况的,但是代码是同一处。
第一种情况是没有cpuset.cpus,那么对比的就是和物理机的核数。
第二种情况是有cpuset.cpus,对比是就是cpuset.cpus的值,并且cpuset.cpus的值一定比物理机核数小,同时也就保证了怎么都不会超过物理真实核数。

result = MIN2(cpu_count, limit_count);

依旧最终选择最小。这里也就发现了一个点,最大值不能超过物理机核数,现在看第一个quota模式,如果period只有正常cpu的一半,然后想用光所有cpu,就必须把quota扩大一倍。其实这样的比率设置和跑满没有区别。这里建议peroid的设置还是和cpu的时钟保值一致最好。这样的比率就接近于物理机的真是核数了。

总结

  1. share和quota是设置参数相对比较多,需要根据自己的情况来开启设置UseContainerCpuShares,PreferContainerQuotaForCPUCount。直接限制cpuset.cpus是比较省心的,系统函数返回的就是已经被限制过的。
  2. jdk只是描述了虚拟核数,但是永远不会超过当前物理机的核数。
点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
JAVA开发工程师
手记
粉丝
1.6万
获赞与收藏
380

关注作者,订阅最新文章

阅读免费教程

  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消