技术标签: Docker 容器 Java JDK https
Sentinel在docker中获取CPU利用率的一个BUG
作者:龟仙老人
Sentinel简介
微服务治理中限流、熔断、降级是一块非常重要的内容。目前市面上开源的组件也不是很多,简单场景可以使用Guava,复杂场景可以选用Hystrix、Sentinel。今天要说的就是Sentinel,Sentinel是一款阿里开源的产品,只需要做较少的定制开发即可大规模线上使用。从使用感受上来说,它有以下几个优点:
docker中获取cpu利用率的BUG
经典的使用场景是服务消费方在调用提供方时,如果提供方是弱依赖,则可设置一个异常比例的降级规则;对于服务提供方提供的接口可设置一个qps或者线程数的限流规则,并再设置一个“保命”的系统自适应限流。系统自适应限流是系统根据自身的情况,如入口qps,总线程数,cpu load,cpu利用率等系统级指标来限制访问量,可谓是最后的保命神器。
Sentinel在docker中获取cpu利用率是有问题的。先看一下获取cpu利用率的代码:
这里获取cpu load和cpu利用率是通过MXBean的方式获取,从Java文档上能看出getSystemLoadAverage和getSystemCpuLoad方法获取的分别是系统的平均load和“归一化”后的cpu利用率。
Java文档 https://docs.oracle.com/javase/8/docs/jre/api/management/extension/com/sun/management/OperatingSystemMXBean.html
如果是在物理机或者虚拟机上运行,这些代码可以获取到我们想要的数据,但是在docker里面就不一定了,docker中获取到的是宿主机的cpu load与cpu利用率。于是去Sentinel下提了个issue(这也是使用开源产品的好处)。没多久回复说用JDK10,但是生产环境中想升级个JDK也并不是那么简单。
github issue https://github.com/alibaba/Sentinel/issues/1146
过了很久之后终于有人通过代码解决了这个问题。
理解系统负荷
初次看到这段代码是蒙圈的,主要是对cpu利用率与cpu load的定义不熟悉,查阅了一些资料得知cpu利用率是指程序的cpu占用时间除以程序的运行时间,比如单核情况下,一个java程序运行了10秒,其中占用了cpu 1秒,那么cpu利用率为10%,注意这个百分比并不一定小于100%,因为有多核的并行能力存在,比如一个4核的机器运行了一个java程序10秒,占用了每个核5秒的cpu时间,那么总的cpu占用时间是20秒,cpu利用率就是200%。但是在OperatingSystemMXBean的文档中指出将其归一化了,也就是cpu利用率再除以cpu核数。cpu load在阮一峰的文章《理解linux系统负荷》(点击原文可查看)中能很好地解释清楚了,概括一下cpu load就是运行中的进程数加上等待运行的进程数。
理解linux系统负荷(点击阅读原文可以查看) https://www.ruanyifeng.com/blog/2011/07/linux_load_average_explained.html
为什么有了cpu利用率还需要cpu load这个指标呢?因为在系统满负荷的情况下,同样是100%的cpu利用率,谁的负荷更高?就需要cpu load来比较了,cpu load不仅表示了当前的cpu利用率,也预示了未来的利用率。
理解了cpu利用率与cpu load再结合Java文档就能明白这段代码的意思了,计算出每次JVM的运行时间差值与占用cpu的时间差值,利用cpu占用时间差值除以JVM运行时间差值,再除以cpu的核数,计算出归一化后的cpu利用率,每次都计算差值是Sentinel为了取到比较精确的“瞬时”cpu利用率,而不是一个历史平均值。
这段代码有三个缺陷,一是准确获取docker分配的cpu核数是从JDK8u131版本开始,之前版本调用OperatingSystemMXBean.getAvailableProcessors 和 Runtime.getRuntime().availableProcessors() 都会返回宿主机的核数,幸好目前使用的版本都大于此版本;二是这段代码只能统计单一进程的cpu占用率,如果容器中运行了两个java程序,那么每个进程只能统计自己占用的cpu而不知道整个系统处于何种状态,从生产环境来看这种情况出现的概率不大,docker容器中运行的一般是单一进程;三是最终算出的cpu利用率取了宿主机cpu利用率和当前进程算出的cpu利用率的较大值,在docker的cpu被限制或者被绑定时,即cpu资源被隔离时,这两个值可能会相差很大,这时也并不太需要关注宿主机的cpu利用率。
我们都知道,说起Docker,第一反应就是在Linux系统安装。那么如果想在Windows系统安装,怎么玩呢?下面凯哥就图文讲讲怎么在Windows11系统下安...
本篇文章聊聊如何使用 Playwright 进行测试用例的录制生成,以及如何在Docker 容器运行测试用例,或许是网上最简单的入门教程。
楼主也做了简单尝试:分布式任务调度平台 → XXL-JOB 初探、分布式任务调度平台 → XXL-JOB 实战
Lius
要把进程运行在容器中,还需要有便捷的SDK或命令来调用Linux的系统功能,从而创建出容器。容器的运行时(runtime)就是运行和管理容器进程、镜像的工具。
尽管复杂,Kubernetes 仍然是目前最流行的编排器,但 HashiCorp 在 Nomad 上的成功也表明,Kubernetes 的替代方案还有发展空间...
Docker公司发明的「容器镜像」技术,创造性地解决了应用打包的难题。改变了一大批诸如容器编排、服务网格和云原生等技术,深刻影响了云计算领域的技术方向。
Docker是一个容器化平台,它以容器的形式将您的应用程序及其所有依赖项打包在一起,以确保您的应用程序在任何环境中无缝运行。
修改配置文件/etc/docker/daemon.json,进入/etc/docker目录。查看是否有daemon.json文件,没有则执行如下命令创建。