JVM监控中的process_cpu_useage监控项分析
一、监控架构说明
Spring Boot 自带监控功能 Actuator,可在应用服务中提供众多 Web 接口(配置接口、度量接口和其它接口共计 13 个),通过这些接口实现对程序内部运行情况监控,比如监控状况、Bean 加载情况、环境变量、日志信息、线程信息等。
二、具体实现:
- 基于 Spring Boot2.0+框架项目中对 Actuator 进行依赖引用(不同打包工具,如 Maven 或 Gradle 配置略有区别),应用启动后提供度量接口(endpoint):
/actuator/prometheus
; - prometheus 中配置基于注册中心(eureka)的 job 自动发现对个应用的度量接口暴露的监控指标进行收集;
- 集成 Grafana,对 JVM 的内存分配、GC 情况进行动态图形化展示(如编号为 4701 的 dashboard)。
三、应用过程中的问题
1. 现象描述:
在落地过程中发现一个比较奇怪的现象:一个 30 个节点的服务(非容器,直接运行在阿里云 ECS 主机上)版本迭代后,个别节点的 CPU 使用率一项中的 process_cpu_usage(字面意思:进程 CPU 使用情况,官方注释:The “recent cpu usage” for the Java Virtual Machine process)指标异常波动(80%-40%反复横跳)的同时,宿主机的系统整体 CPU 使用率却稳的一匹(稳定 10%),环境说明如下:
- ECS 配置:4 核 8G(通过超线程技术在 2 个物理核上虚拟出 4 个逻辑核,内存 8GB)
- 关键 JAVA_OPTS 参数:-Xmx4G -Xms4G -XX:+UseG1GC
- 横向对比监控项 system_cpu_usage(字面意思:系统 cpu 使用情况,官方注释:The “recent cpu usage” for the whole system)
2. 知识储备:
- 描述系统的 CPU 性能的最佳指标是 CPU 使用率(单位时间内 CPU 使用情况的统计);Linux 作为一个多任务操作系统,以节拍率为单位将 CPU 时间划分为小的时间片,使用全局变量 Jiffies 记录开机以来的节拍数,通过调度器将时间片轮流分配给各个任务使用(每次调度 Jiffies 的值加 1),通过 /proc 虚拟文件系统中的 /proc/stat 提供系统的 CPU 和任务统计信息(内容就是不同场景下 CPU 的累加节拍数,即累计 CPU 时间)
- 进程级的 CPU 使用分布主要分为:用户态 CPU 时间、内核态 CPU 时间、运行虚拟机 CPU 时间、等待 I/O 的 CPU 时间,对应 pidstat 工具输出中的:%user、%system、%guest、%wait
- 基本上所有工具对 cpu 的使用状态统计分析都是基于/proc/stat 和 /proc/[pid]/stat,这也是 process_cpu_usage 指标和 system_cpu_usage 的指标数据来源。
- cpu 使用率常用计算公式:
3. 分析:
一开始就容易陷入了误区:process_cpu_usage 和 system_cpu_usage 放在一起,很容易让人想到这俩指标分别是进程的用户态 cpu 使用统计(进程性能相关)和进程内核态 cpu 使用统计(内核线程或者系统调用性能相关);经过翻文档确认这种理解有误;初步确认:process_cpu_usage 是 java 应用进程最近的 cpu 使用率指标;system_cpu_usage 是 ECS 主机整体 cpu 使用率指标;那么问题就来了:
- 既然 process_cpu_usage 是 java 进程 cpu 使用率,这台主机又是独享的(只有这一个业务进程,其他系统应用资源耗费都很低)为什么在 process_cpu_usage 指标一度达到 100% 的时候,system_cpu_usage 指标只有 20%,如果解释为 process_cpu_usage 体现的是单核 cpu 使用率(4 核系统中约等于系统整体 cpu 使用率的 1/4),那在稳定运行的情况下,process_cpu_usage 应该一直是 system_cpu_usage 指标的 4 倍,但是根据监控显示,其他监控曲线正常的节点上,这俩指标的数值基本上是重合的(趋势也一致),这种说法明显不对;
- 如果根据稳定运行的情况下两个指标的数值来判断的话,(高峰期/17:00)约为 30%,此时在主机上通过 top、ps 和 pidstat 命令查看进程 cpu 使用情况发现,瞬时值约为 100%(编号为 3 的 cpu 完全占用,满载应为 400%),1min/5min/15min 系统负载为约为 1(满载为 4);process_cpu_usage 和 system_cpu_usage 可判定为基于多核的近期 cpu 使用率(也与官方注释相符合,因为分析时收集数据存在一定时间差导致略有出入,整体可以接受),又没法解释:process_cpu_usage 指标达到 100% 的时候,system_cpu_usage 指标只有 20% 的现象;
4. 结论:
仍未找出监控系统中 process_cpu_usage 指标达到 100% 时 system_cpu_usage 数值为 20% 现象的根本原因,通过重启解决;
因为在应用服务正常运行期间各指标监控曲线应该是平滑的,在没有人为操作、业务流量没有变化的前提下监控曲线出现陡增陡降的现象,将其判定为异常状况,稳妥期间进行进程重启,重启后监控曲线也的确恢复平滑;表示异常状况恢复,但是原因没有定位到;下次再发生的时候,情况允许的话保留一下现场再次排查,希望能找到蛛丝马迹,各位同学有好的想法或者提议也希望不吝赐教;