尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Linux服务器CPU核心级监控:从mpstat到Prometheus的实战指南

Linux服务器CPU核心级监控:从mpstat到Prometheus的实战指南 1. 项目概述为什么需要细粒度监控CPU使用率在Linux服务器运维、性能调优乃至日常开发排查线上问题的过程中我们经常会遇到一个看似简单却至关重要的问题系统的整体CPU使用率看起来不高但应用响应却异常缓慢。这时候一个笼统的top命令输出的%Cpu(s)可能就会“欺骗”我们。真正的问题可能隐藏在某个或某几个CPU核心上——可能是单个核心被某个进程的单个线程跑满导致处理该线程请求的任务队列严重阻塞也可能是由于进程的CPU亲和性设置不当大量进程挤在少数几个核心上“内卷”而其他核心却在“围观”。因此“看每个CPU的使用率”这个需求其核心价值在于实现细粒度的性能洞察与精准的问题定位。它不再是看一个整体的平均数字而是像给服务器的每个“计算引擎”都装上独立的仪表盘实时监控它们各自的负载情况。这对于诊断多线程应用的性能瓶颈、优化NUMA架构下的内存访问、排查因中断或软中断不均衡导致的网络延迟抖动等问题都是不可或缺的第一步。无论是系统管理员、SRE工程师还是后端开发者掌握这套“分核心监控”的方法都能让你在性能问题的迷雾中更快地找到那盏指路的灯。2. 核心工具与命令解析Linux生态提供了从经典到现代、从命令行到图形化的一系列工具来满足这个需求。它们各有侧重适用于不同的场景。2.1 经典全能王mpstat来自sysstat包mpstat是sysstat工具集里的明星专门用于汇报每个处理器的统计信息。它的输出专业、详细是进行自动化监控和性能分析的基石。安装与基本使用在大多数发行版上可以通过包管理器安装# Ubuntu/Debian sudo apt-get install sysstat # CentOS/RHEL/Fedora sudo yum install sysstat # 或 sudo dnf install sysstat安装后最简单的用法是mpstat -P ALL 1。这里的-P ALL表示报告所有CPU核心-P 0表示仅CPU 0-P 1,2,3表示指定核心1表示每隔1秒输出一次。按CtrlC终止。输出字段深度解读执行命令后你会看到类似下面的输出首次输出为自启动以来的平均值后续为间隔内的快照Linux 5.4.0-xx-generic (hostname) 04/10/2024 _x86_64_ (8 CPU) 04:20:00 PM CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle 04:20:01 PM all 8.12 0.00 2.25 0.12 0.00 0.25 0.00 0.00 0.00 89.25 04:20:01 PM 0 15.00 0.00 4.00 0.00 0.00 0.00 0.00 0.00 0.00 81.00 04:20:01 PM 1 2.00 0.00 1.00 1.00 0.00 1.00 0.00 0.00 0.00 95.00 ... (其他CPU核心)%usr: 用户态进程运行时间占比不包括nice值为负的进程。这是你的应用程序代码消耗的CPU。%nice: 运行在低优先级nice值大于0的用户态进程时间占比。通常不高。%sys: 内核态运行时间占比。系统调用、中断处理、内核线程等消耗的CPU。如果这个值持续异常高可能意味着内核资源竞争激烈或驱动有问题。%iowait: CPU等待磁盘I/O完成的时间占比。这是关键指标如果某个核心的%iowait很高说明挂在这个核心上的进程频繁等待IO可能遇到了存储瓶颈。但注意现代Linux中iowait并不完全等同于CPU空闲它表示CPU在至少有一个IO未完成时的空闲状态。%irq: 处理硬件中断的时间占比。%soft: 处理软中断的时间占比。网络包处理特别是高流量场景会显著推高这个值。如果某个核心的%soft异常高可能是网络中断绑定IRQ affinity不均衡需要优化。%steal: 在虚拟化环境中被宿主机“偷走”的时间占比。如果你的虚拟机CPU资源被宿主机过度分配或限制这个值会升高。%guest: 运行虚拟处理器的时间运行客户机操作系统。%idle: CPU空闲时间占比。实操心得不要只看%idle。一个核心%idle很高可能只是没活干但%iowait或%soft高则明确指示了潜在问题。结合all行和每个核心的行对比能立刻发现负载是否均衡。例如如果CPU0的%usr是80%而其他核心都低于10%那很可能有一个单线程热点进程绑在了CPU0上。2.2 交互式实时监控top/htoptop命令是大多数人的首选它本身也支持按核心查看。在top中切换视图启动top。按下数字键1。你会发现顶部的%Cpu(s)行展开为每一行对应一个逻辑CPU核心的详细状态。再次按1可以折叠回汇总视图。htop的进阶可视化htop是top的增强版界面更友好。默认情况下它顶部就以条形图形式展示了每个CPU核心的使用率。安装sudo apt install htop或sudo yum install htop。运行htop。按F2进入设置选择Meters你可以添加或调整顶部的显示元素例如将 “CPU” 仪表改为按核心显示或者添加“CPU平均负载”、“内存”等。htop的颜色编码非常直观蓝色表示低优先级线程绿色表示普通进程红色表示内核任务让你一眼就能看出CPU时间花在了哪里。注意事项top和htop显示的CPU使用率是瞬时值或短时间内的采样平均值对于捕捉瞬间尖峰非常有用但对于计算长时间段的精确平均值不如mpstat或后续的sar。2.3 性能分析利器perf当需要定位到是哪个进程的哪个线程在消耗特定CPU核心时perf工具链就派上用场了。perf top可以按CPU核心进行过滤。使用perf top监控指定CPUsudo perf top -C 0,1这条命令会监控CPU核心0和核心1上的性能事件默认是周期采样并实时显示消耗这些CPU资源最多的函数符号。这对于诊断内核或特定应用程序在某个核心上的热点代码路径极其有效。结合mpstat和perf定位问题假设mpstat发现CPU3的%sys异常高。我们可以用pidstat -u -p ALL 1 | grep -v “%CPU” | sort -k7 -rn快速找出内核态时间高的进程。然后用sudo perf top -p PID -C 3来专注观察这个进程在CPU3上的具体函数调用情况。2.4 系统活动报告sar历史数据回顾sar同样是sysstat包的一部分它的强大之处在于能查看历史数据。sysstat默认会通过cron作业/etc/cron.d/sysstat每10分钟收集一次系统指标并保存到/var/log/sa/目录下。查看过去某个时间点每个CPU的使用率# 查看当天04:20:00到04:30:00之间所有CPU核心的统计数据每秒一次 sar -P ALL -s 04:20:00 -e 04:30:00 1查看历史文件例如sa10# 查看10号那天的数据-P ALL表示所有CPU sar -P ALL -f /var/log/sa/sa10sar的数据对于回溯分析历史性能问题、生成趋势报告至关重要。比如你可以用它来证明在昨天下午的流量高峰期间并不是所有CPU都满载只是其中两个核心的%soft激增从而将排查方向引向网络中断处理。2.5 底层信息源/proc/stat所有上述工具的数据最终都来源于Linux内核暴露的/proc文件系统特别是/proc/stat文件。直接查看它可以获得最原始的数据。cat /proc/stat你会看到以cpu、cpu0、cpu1...开头的多行。每一行的数字分别代表单位是USER_HZ通常为1/100秒usernicesystemidleiowaitirqsoftirqstealguestguest_nice这些数字是自系统启动以来的累计值。通过计算两个时间点之间的差值就可以得到这段时间内的CPU使用率百分比。这也是所有监控工具如Zabbix、Prometheus node_exporter采集CPU指标的基础。重要提示对于超线程Hyper-Threading的CPU操作系统会将每个物理核心上的两个逻辑处理器线程都识别为独立的CPU如cpu0, cpu1。mpstat、top等工具显示的是逻辑CPU的使用率。在分析时需要结合物理核心来理解因为共享同一物理核心的两个逻辑CPU会竞争执行资源。3. 高级场景与实战技巧掌握了基础命令我们来看几个更贴近实战的进阶场景和脚本技巧。3.1 脚本化监控与告警对于自动化运维我们经常需要写脚本定期采集每个核心的指标并在超过阈值时触发告警。示例脚本监控任一核心的idle值低于10%并告警#!/bin/bash # 文件名check_cpu_per_core.sh THRESHOLD10 # idle阈值低于此值告警 INTERVAL5 # 采样间隔秒数 LOG_FILE/var/log/cpu_alert.log while true; do TIMESTAMP$(date %Y-%m-%d %H:%M:%S) # 使用mpstat获取最近5秒的数据跳过前3行头部信息 mpstat -P ALL $INTERVAL 1 | awk -v threshold$THRESHOLD -v ts$TIMESTAMP NR3 $2 ~ /^[0-9]$/ { # 处理每个核心的行排除“all”行 core $2; idle $NF; # 最后一列是%idle if (idle threshold) { printf [%s] 警告: CPU核心 %s 空闲率过低: %.2f%%\n, ts, core, idle $LOG_FILE # 这里可以集成邮件、钉钉、企业微信等告警接口 # 例如: send_alert CPU核心${core}负载过高空闲率${idle}% } } sleep $INTERVAL done这个脚本每5秒采样一次检查每个逻辑CPU核心的%idle是否低于10%并将告警写入日志。你可以在此基础上扩展加入对%iowait、%soft的监控或者集成到你的监控系统中。3.2 诊断CPU负载不均衡问题多线程应用性能不佳有时是因为线程调度不均衡。我们可以用一系列命令组合来诊断。第一步用mpstat或top 1确认不均衡现象。第二步用pidstat查看每个进程在每个CPU上的分布。# 每2秒采样一次输出5次并显示进程在每个CPU上的运行情况 pidstat -u -l 2 5观察输出中%CPU列和CPU列看是否有进程的线程总是集中在某个特定的CPU核心上。第三步检查进程的CPU亲和性affinity。# 查看进程pid当前的CPU亲和性掩码 taskset -pc pid输出如pid 12345‘s current affinity list: 0-3表示该进程的线程可以运行在CPU 0,1,2,3上。如果掩码范围很小例如只允许在CPU0上运行可能就是导致不均衡的原因。第四步使用perf进行更细粒度的分析。# 记录系统范围内所有CPU上发生的事件如周期采样10秒钟 sudo perf record -a -g -- sleep 10 # 生成报告并查看在特定CPU例如CPU1上的调用链 sudo perf report --cpu1这能帮你看到在负载高的核心上CPU时间具体花在了哪些函数上。3.3 容器环境下的CPU监控在Docker或Kubernetes环境中由于cgroups的隔离从宿主机用top或mpstat看到的CPU使用率是物理核心的全局情况。要查看某个容器内部的每个CPU使用率需要进入容器命名空间。对于Docker容器# 进入容器内部执行mpstat docker exec container_id_or_name mpstat -P ALL 1前提是容器镜像中安装了sysstat包。如果没有可以考虑在构建镜像时加入或者使用基于宿主机但通过cgroup信息推算的工具如cadvisor。更通用的方法使用pidstat追踪容器内进程找到容器内关键进程在宿主机上的PID。docker top container_id使用pidstat监控这个PID及其所有线程-t参数并显示CPU编号-u参数已隐含但需要结合-p和-t。pidstat -t -p 宿主机的PID 1输出中的CPU列会显示每个线程当前运行在哪个逻辑CPU上%usr和%system列显示了使用率。这相当于从外部窥探了容器进程在宿主机CPU核心上的分布情况。踩坑记录在超线程开启的机器上容器对CPU的限制如docker run --cpuset-cpus0-3指的是逻辑CPU。你可能将容器绑定到逻辑CPU 0,1但它们可能对应同一个物理核心的两个超线程。这意味着容器内进程仍然会共享物理核心的资源在计算密集型任务中可能产生预期之外的性能干扰。绑定CPU时最好先了解物理核心的拓扑结构lscpu -p。4. 可视化与长期监控方案命令行工具适合即时排查但长期趋势分析和团队协作需要可视化。4.1 使用 atop 进行高级记录与回放atop是一个功能强大的交互式监控工具但它最独特的特性是能以高频率如默认10秒将系统性能数据记录到文件中之后可以像“时光机”一样回放。# 启动atop记录每30秒采样一次记录到 /var/log/atop/ 目录 sudo systemctl start atop # 通常atop服务已配置为定时记录 # 回放某个历史文件例如2024年04月10日的日志 sudo atop -r /var/log/atop/atop_20240410在atop回放界面你可以按C键切换到CPU视图看到每个CPU核心在不同历史时刻的使用率明细结合按P进程视图、D磁盘视图等可以进行非常全面的历史故障根因分析。4.2 集成到PrometheusGrafana监控栈对于生产环境搭建基于Prometheus的监控系统是标准做法。部署 node_exporter在被监控的Linux服务器上运行node_exporter它会暴露大量指标包括每个CPU核心的使用率。相关指标是node_cpu_seconds_total{cpu0, modeuser}node_cpu_seconds_total{cpu0, modesystem}node_cpu_seconds_total{cpu0, modeidle}... 以此类推cpu1,cpu2...Prometheus采集配置Prometheus定期抓取node_exporter的指标。Grafana绘图在Grafana中创建一个新的Dashboard。添加一个Panel数据源选择Prometheus。使用PromQL查询来绘制每个核心的CPU使用率。一个常用的查询公式是(1 - avg(rate(node_cpu_seconds_total{cpu0, modeidle}[5m])) by (cpu)) * 100这个查询计算的是CPU0在过去5分钟内的平均非空闲率即使用率。你可以复制这个查询为cpu1、cpu2...分别创建曲线或者使用by (cpu)在一个图里显示所有核心。你还可以创建更复杂的图表比如堆叠面积图来显示每个核心上user、system、iowait等不同模式的占比一目了然地看到负载构成和均衡情况。4.3 编写自定义的监控脚本有时你可能需要非常特定的监控逻辑。比如监控某个特定进程池例如Nginx worker进程在各个CPU核心上的分布均匀性。这时可以结合ps、awk和mpstat来写脚本。示例监控Nginx worker进程的CPU亲和性分布#!/bin/bash # 检查每个Nginx worker进程当前运行在哪个CPU上并统计分布 NGINX_PIDS$(pgrep -x nginx | head -1) # 获取master进程PID if [ -z $NGINX_PIDS ]; then echo Nginx is not running. exit 1 fi # 获取所有worker进程的PIDmaster进程的子进程 WORKER_PIDS$(pstree -p $NGINX_PIDS | grep -o nginx([0-9]\) | grep -o [0-9]\) declare -A CPU_COUNT for pid in $WORKER_PIDS; do # 通过/proc文件系统获取进程最后一次运行的CPU cpu$(taskset -pc $pid 2/dev/null | awk -F: {print $2} | awk {print $NF}) # 或者使用更直接的方法需要root: cat /proc/$pid/stat | awk {print $39} if [[ $cpu ~ ^[0-9]$ ]]; then ((CPU_COUNT[$cpu])) fi done echo Nginx Worker进程CPU核心分布统计: for cpu in ${!CPU_COUNT[]}; do echo CPU $cpu: ${CPU_COUNT[$cpu]} 个worker进程 done这个脚本可以帮助你验证Nginx的worker_cpu_affinity配置是否生效或者发现worker进程是否被不均衡地调度到了某些核心上。
返回列表