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

jvm是如何做容器识别的

标签:
Java

jvm已经支持了容器的识别。

-XX:+UseContainerSupport

容器支持的参数已经默认是开启状态。下面我们就来看看作为一个进程,他是如何识别外部的资源限制的。

核心代码

 optResult = determineType("/proc/self/mountinfo", "/proc/cgroups", "/proc/self/cgroup");

代码主要围绕着3个文件来进行读取。就是上面方法中的3个参数。我们后面根据代码来看看这3个文件的作用。
了解cgroup的同学,了解资源的限制是写在了文件路径下的。所以代码的核心的就是去找到文件路径。填充如下的class数据数据、

public class CgroupInfo {

    private final String name;
    private final int hierarchyId;
    private final boolean enabled;
    private String mountPoint;
    private String mountRoot;
    private String cgroupPath;
    
 }

第一步从 /proc/cgroups从获取子系统的信息。
jdk默认识别的子系统有6种,他们是作为常量写在java文件中的。

    private static final String CPU_CTRL = "cpu";
    private static final String CPUACCT_CTRL = "cpuacct";
    private static final String CPUSET_CTRL = "cpuset";
    private static final String BLKIO_CTRL = "blkio";
    private static final String MEMORY_CTRL = "memory";
    private static final String PIDS_CTRL = "pids";

第二步是从/proc/self/mountinfo获取mountpoint,mountroot。
这里jdk直接匹配了正则。

    private static final Pattern MOUNTINFO_PATTERN = Pattern.compile(
        "^[^\\s]+\\s+[^\\s]+\\s+[^\\s]+\\s+" + // (1), (2), (3)
        "([^\\s]+)\\s+([^\\s]+)\\s+" +         // (4), (5)     - group 1, 2: root, mount point
        "[^-]+-\\s+" +                         // (6), (7), (8)
        "([^\\s]+)\\s+" +                      // (9)          - group 3: filesystem type
        ".*$");                                // (10), (11)

这里的信息,我们可以通过自己cat或者注释来看。

    /*
     * From https://www.kernel.org/doc/Documentation/filesystems/proc.txt
     *
     *  36 35 98:0 /mnt1 /mnt2 rw,noatime master:1 - ext3 /dev/root rw,errors=continue
     *  (1)(2)(3)   (4)   (5)      (6)      (7)   (8) (9)   (10)         (11)
     *
     *  (1) mount ID:  unique identifier of the mount (may be reused after umount)
     *  (2) parent ID:  ID of parent (or of self for the top of the mount tree)
     *  (3) major:minor:  value of st_dev for files on filesystem
     *  (4) root:  root of the mount within the filesystem
     *  (5) mount point:  mount point relative to the process's root
     *  (6) mount options:  per mount options
     *  (7) optional fields:  zero or more fields of the form "tag[:value]"
     *  (8) separator:  marks the end of the optional fields
     *  (9) filesystem type:  name of filesystem of the form "type[.subtype]"
     *  (10) mount source:  filesystem specific information or "none"
     *  (11) super options:  per super block options
     */

在获取到mountpoint,mountroot之后,我们还差最后一个cgroupPath。
这个数据就是从/proc/self/cgroup中获取。
/proc/self/cgroup的数据如下


  /*
     * Sets the path to the cgroup controller for cgroups v1 based on a line
     * in /proc/self/cgroup file (represented as the 'tokens' array).
     *
     * Note that multiple controllers might be joined at a single path.
     *
     * Example:
     *
     * 7:cpu,cpuacct:/system.slice/docker-74ad896fb40bbefe0f181069e4417505fffa19052098f27edf7133f31423bc0b.scope
     *
     * => tokens = [ "7", "cpu,cpuacct", "/system.slice/docker-74ad896fb40bbefe0f181069e4417505fffa19052098f27edf7133f31423bc0b.scope" ]
     */

通过切割字符串,我们获取到了cgroupPath。
通过以上的3个操作,我们最终构造出了完整的cgroup路径,后面的部分就是根据路径读取配置的文件名即可。

小结

  1. /proc/cgroups可以获取cgroup的子系统
  2. /proc/self/mountinfo可以获得挂载点
  3. /proc/self/cgroup可以获取cgroup的path
点击查看更多内容
2人点赞

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

评论

作者其他优质文章

正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

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

举报

0/150
提交
取消