跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
Shell / Bash

运维排查问题常用工具与方法论

综述由AI生成运维排查问题的常用工具集与分析方法论。涵盖 CPU、内存、磁盘 IO、网络及系统负载五大维度的监控手段,包括 top、vmstat、perf、valgrind、iotop、netstat、tcpdump 等核心命令。重点讲解了火焰图的原理与应用,包括 on-CPU、off-CPU 及差分火焰图的生成与分析流程。通过 Nginx 集群异常案例,演示了如何结合流量、响应时间及 CPU 火焰图定位根因,最终通过更换 JSON 解析库和优化配置解决性能瓶颈问题。

观心发布于 2025/2/7更新于 2026/6/225 浏览
运维排查问题常用工具与方法论

背景

有时候会遇到一些疑难杂症,监控插件并不能一眼立马发现问题的根源。这时候就需要登录服务器进一步深入分析问题的根源。分析问题需要有一定的技术经验积累,并且有些问题涉及到的领域非常广,才能定位到问题。所以,分析问题和踩坑是非常锻炼一个人的成长和提升自我能力。如果我们有一套好的分析工具,那将是事半功倍,能够帮助大家快速定位问题,节省大家很多时间做更深入的事情。

说明

本文主要介绍各种问题定位的工具以及结合案例分析问题。

分析问题的方法论

套用 5W2H 方法,可以提出性能分析的几个问题:

  • What:现象是什么样的
  • When:什么时候发生
  • Why:为什么会发生
  • Where:哪个地方发生的问题
  • How much:耗费了多少资源
  • How to do:怎么解决问题

CPU 分析

说明

针对应用程序,我们通常关注的是内核 CPU 调度器功能和性能。

线程的状态分析主要是分析线程的时间用在什么地方,而线程状态的分类一般分为:

  1. on-CPU:执行中,执行中的时间通常又分为用户态时间 user 和系统态时间 sys。
  2. off-CPU:等待下一轮上 CPU,或者等待 I/O、锁、换页等等,其状态可以细分为可执行、匿名换页、睡眠、锁、空闲等状态。

如果大量时间花在 CPU 上,对 CPU 的剖析能够迅速解释原因;如果系统时间大量处于 off-cpu 状态,定位问题就会费时很多。但是仍然需要清楚一些概念:处理器、核、硬件线程、CPU 内存缓存、时钟频率、每指令周期数 CPI 和每周期指令数 IPC、CPU 指令、使用率、用户时间/内核时间、调度器、运行队列、抢占、多进程、多线程、字长。

分析工具

  • uptime, vmstat, mpstat, top, pidstat:只能查询到 cpu 及负载的使用情况。
  • perf:可以跟踪到进程内部具体函数耗时情况,并且可以指定内核函数进行统计,指哪打哪。

使用方式

# 查看系统 cpu 使用情况
top

# 查看所有 cpu 核信息
mpstat -P ALL 1

# 查看 cpu 使用情况以及平均负载
vmstat 1

# 进程 cpu 的统计信息
pidstat -u 1 -p pid

# 跟踪进程内部函数级 cpu 使用情况
perf top -p pid -e cpu-clock

内存分析

说明

内存是为提高效率而生,实际分析问题的时候,内存出现问题可能不只是影响性能,而是影响服务或者引起其他问题。同样对于内存有些概念需要清楚:主存、虚拟内存、常驻内存、地址空间、OOM、页缓存、缺页、换页、交换空间、交换、用户分配器 libc/glibc/libmalloc/mtmalloc、LINUX 内核级 SLUB 分配器。

分析工具

  • free, vmstat, top, pidstat, pmap:只能统计内存信息以及进程的内存使用情况。
  • valgrind:可以分析内存泄漏问题。
  • dtrace:动态跟踪。需要对内核函数有很深入的了解,通过 D 语言编写脚本完成跟踪。

使用方式

# 查看系统内存使用情况
free -m

# 虚拟内存统计信息
vmstat 1

# 查看系统内存情况
top

# 1s 采集周期,获取内存的统计信息
pidstat -p pid -r 1

# 查看进程的内存映像信息
pmap -d pid

# 检测程序内存问题
valgrind --tool=memcheck --leak-check=full --log-file=./log.txt ./程序名

磁盘 IO 分析

说明

磁盘通常是计算机最慢的子系统,也是最容易出现性能瓶颈的地方,因为磁盘离 CPU 距离最远而且 CPU 访问磁盘要涉及到机械操作,比如转轴、寻轨等。访问硬盘和访问内存之间的速度差别是以数量级来计算的,就像 1 天和 1 分钟的差别一样。要监测 IO 性能,有必要了解一下基本原理和 Linux 是如何处理硬盘和内存之间的 IO 的。

在理解磁盘 IO 之前,同样我们需要理解一些概念,例如:文件系统、VFS、文件系统缓存、页缓存 page cache、缓冲区高速缓存 buffer cache、目录缓存、inode、inode 缓存、noop 调用策略。

分析工具

  • iotop:查看系统 io 信息。
  • iostat:统计 io 详细信息。
  • pidstat:查看进程级 io 的信息。
  • perf:查看系统 IO 的请求,比如可以在发现系统 IO 异常时,使用该命令进行调查,就能指定到底是什么原因导致的 IO 异常。

使用方式

# 查看系统 io 信息
iotop

# 统计 io 详细信息
iostat -d -x -k 1 10

# 查看进程级 io 的信息
pidstat -d 1 -p pid

# 查看系统 IO 的请求
perf record -e block:block_rq_issue -ag
^C
perf report

网络分析

说明

网络的监测是所有 Linux 子系统里面最复杂的,有太多的因素在里面,比如:延迟、阻塞、冲突、丢包等,更糟的是与 Linux 主机相连的路由器、交换机、无线信号都会影响到整体网络并且很难判断是因为 Linux 网络子系统的问题还是别的设备的问题,增加了监测和判断的复杂度。现在我们使用的所有网卡都称为自适应网卡,意思是说能根据网络上的不同网络设备导致的不同网络速度和工作模式进行自动调整。

分析工具

  • netstat:显示网络统计信息。
  • ss:显示 TCP 连接、sockets 摘要信息。
  • sar:查看网络 IO。
  • tcpdump:抓包以包为单位进行输出。
  • tcpflow:抓包以流为单位显示数据内容。

使用方式

# 显示网络统计信息
netstat -s

# 显示当前 UDP 连接状况
netstat -nu

# 显示 UDP 端口号的使用情况
netstat -apu

# 统计机器中网络连接各个状态个数
netstat -a | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'

# 显示 TCP 连接
ss -t -a

# 显示 sockets 摘要信息
ss -s

# 显示所有 udp sockets
ss -u -a

# tcp,etcp 状态
sar -n TCP,ETCP 1

# 查看网络 IO
sar -n DEV 1

# 抓包以包为单位进行输出
tcpdump -i eth1 host 192.168.1.1 and port 80

# 抓包以流为单位显示数据内容
tcpflow -cp host 192.168.1.1

系统负载分析

说明

Load 就是对计算机干活多少的度量(WikiPedia:the system Load is a measure of the amount of work that a compute system is doing)。简单的说是进程队列的长度。Load Average 就是一段时间(1 分钟、5 分钟、15 分钟)内平均 Load。

分析工具

  • uptime, top, vmstat:查看负载情况。
  • strace:统计系统调用耗时情况。
  • dmesg:查看内核日志信息。

使用方式

# 查看负载情况
uptime
top
vmstat

# 统计系统调用耗时情况
strace -c -p pid

# 跟踪指定的系统操作例如 epoll_wait
strace -T -e epoll_wait -p pid

# 查看内核日志信息
dmesg

火焰图 (Flame Graph)

说明

火焰图是 Brendan Gregg 创建的一种性能分析图表,因为它的样子近似火焰而得名。

火焰图主要是用来展示 CPU 的调用栈。

  • y 轴:表示调用栈,每一层都是一个函数。调用栈越深,火焰就越高,顶部就是正在执行的函数,下方都是它的父函数。
  • x 轴:表示抽样数,如果一个函数在 x 轴占据的宽度越宽,就表示它被抽到的次数多,即执行的时间长。注意,x 轴不代表时间,而是所有的调用栈合并后,按字母顺序排列的。

火焰图就是看顶层的哪个函数占据的宽度最大。只要有'平顶'(plateaus),就表示该函数可能存在性能问题。颜色没有特殊含义,因为火焰图表示的是 CPU 的繁忙程度,所以一般选择暖色调。

常见的火焰图类型有 On-CPU、Off-CPU、Memory、Hot/Cold、Differential 等等。

安装依赖库

# 安装 systemtap,默认系统已安装
yum install systemtap systemtap-runtime

# 内核调试库必须跟内核版本对应,例如:uname -r 2.6.18-308.el5
kernel-debuginfo-2.6.18-308.el5.x86_64.rpm
kernel-devel-2.6.18-308.el5.x86_64.rpm
kernel-debuginfo-common-2.6.18-308.el5.x86_64.rpm

# 安装内核调试库
debuginfo-install --enablerepo=debuginfo search kernel
debuginfo-install --enablerepo=debuginfo search glibc

安装 FlameGraph 工具

git clone https://github.com/brendangregg/FlameGraph.git
cd FlameGraph

CPU 级别火焰图

CPU 占用过高,或者使用率提不上来,你能快速定位到代码的哪块有问题吗?一般的做法可能就是通过日志等方式去确定问题。现在我们有了火焰图,能够非常清晰的发现哪个函数占用 CPU 过高,或者过低导致的问题。

on-CPU

CPU 占用过高,执行中的时间通常又分为用户态时间 user 和系统态时间 sys。

使用方式:

# on-CPU user
sh ngx_on_cpu_u.sh pid

# 进入结果目录
cd ngx_on_cpu_u

# on-CPU kernel
sh ngx_on_cpu_k.sh pid

# 进入结果目录
cd ngx_on_cpu_k

# 开一个临时端口 8088
python -m SimpleHTTPServer 8088

# 打开浏览器输入地址 127.0.0.1:8088/pid.svg

DEMO 代码:

#include <stdio.h>
#include <stdlib.h>

void foo3() { }

void foo2() { 
    int i;
    for(i = 0 ; i < 10; i++) foo3(); 
}

void foo1() { 
    int i;
    for(i = 0; i< 1000; i++) foo3(); 
}

int main(void) { 
    int i;
    for( i =0; i< 1000000000; i++) { 
        foo1(); 
        foo2(); 
    } 
}

off-CPU

CPU 过低,利用率不高。等待下一轮 CPU,或者等待 I/O、锁、换页等等,其状态可以细分为可执行、匿名换页、睡眠、锁、空闲等状态。

使用方式:

# off-CPU user
sh ngx_off_cpu_u.sh pid

# 进入结果目录
cd ngx_off_cpu_u

# off-CPU kernel
sh ngx_off_cpu_k.sh pid

# 进入结果目录
cd ngx_off_cpu_k

# 开一个临时端口 8088
python -m SimpleHTTPServer 8088

# 打开浏览器输入地址 127.0.0.1:8088/pid.svg

内存级别火焰图

如果线上程序出现了内存泄漏,并且只在特定的场景才会出现。这个时候我们怎么办呢?有什么好的方式和工具能快速的发现代码的问题呢?同样内存级别火焰图帮你快速分析问题的根源。

使用方式:

sh ngx_on_memory.sh pid

# 进入结果目录
cd ngx_on_memory

# 开一个临时端口 8088
python -m SimpleHTTPServer 8088

# 打开浏览器输入地址 127.0.0.1:8088/pid.svg

性能回退 - 红蓝差分火焰图

你能快速定位 CPU 性能回退的问题么?如果你的工作环境非常复杂且变化快速,那么使用现有的工具是来定位这类问题是很具有挑战性的。当你花掉数周时间把根因找到时,代码已经又变更了好几轮,新的性能问题又冒了出来。主要可以用到每次构建中,每次上线做对比看,如果损失严重可以立马解决修复。

通过抓取了两张普通的火焰图,然后进行对比,并对差异部分进行标色:红色表示上升,蓝色表示下降。差分火焰图是以当前('修改后')的 profile 文件作为基准,形状和大小都保持不变。因此你通过色彩的差异就能够很直观的找到差异部分,且可以看出为什么会有这样的差异。

使用方式:

cd FlameGraph

# 抓取代码修改前的 profile 1 文件
perf record -F 99 -p pid -g -- sleep 30
perf script > out.stacks1

# 抓取代码修改后的 profile 2 文件
perf record -F 99 -p pid -g -- sleep 30
perf script > out.stacks2

# 生成差分火焰图
./stackcollapse-perf.pl ../out.stacks1 > out.folded1
./stackcollapse-perf.pl ../out.stacks2 > out.folded2
./difffolded.pl out.folded1 out.folded2 | ./flamegraph.pl > diff2.svg

DEMO 代码:

test.c

#include <stdio.h>
#include <stdlib.h>

void foo3() { }

void foo2() { 
    int i;
    for(i = 0 ; i < 10; i++) foo3(); 
}

void foo1() { 
    int i;
    for(i = 0; i< 1000; i++) foo3(); 
}

int main(void) { 
    int i;
    for( i =0; i< 1000000000; i++) { 
        foo1(); 
        foo2(); 
    } 
}

test1.c

#include <stdio.h>
#include <stdlib.h>

void foo3() { }

void foo2() { 
    int i;
    for(i = 0 ; i < 10; i++) foo3(); 
}

void foo1() { 
    int i;
    for(i = 0; i< 1000; i++) foo3(); 
}

void add() { 
    int i;
    for(i = 0; i< 10000; i++) foo3(); 
}

int main(void) { 
    int i;
    for( i =0; i< 1000000000; i++) { 
        foo1(); 
        foo2(); 
        add(); 
    } 
}

案例分析

接入层 nginx 集群异常现象

通过监控插件发现在 2017.09.25 19 点 nginx 集群请求流量出现大量的 499,5xx 状态码。并且发现机器 cpu 使用率升高,目前一直持续中。

分析 nginx 相关指标

分析 nginx 请求流量

通过上图发现流量并没有突增,反而下降了,跟请求流量突增没关系。

分析 nginx 响应时间

通过上图发现 nginx 的响应时间有增加,可能跟 nginx 自身有关系或者跟后端 upstream 响应时间有关系。

分析 nginx upstream 响应时间

通过上图发现 nginx upstream 响应时间有增加,目前猜测可能后端 upstream 响应时间拖住 nginx,导致 nginx 出现请求流量异常。

分析系统 cpu 情况

通过 top 观察系统指标

top

发现 nginx worker cpu 比较高。

分析 nginx 进程内部 cpu 情况

perf top -p pid

发现主要开销在 free, malloc, json 解析上面。

火焰图分析 cpu

生成用户态 cpu 火焰图

# on-CPU user
sh ngx_on_cpu_u.sh pid

# 进入结果目录
cd ngx_on_cpu_u

# 开一个临时端口 8088
python -m SimpleHTTPServer 8088

# 打开浏览器输入地址 127.0.0.1:8088/pid.svg

发现代码里面有频繁的解析 json 操作,并且发现这个 json 库性能不高,占用 cpu 挺高。

案例总结

  1. 分析请求流量异常,得出 nginx upstream 后端机器响应时间拉长。
  2. 分析 nginx 进程 cpu 高,得出 nginx 内部模块代码有耗时的 json 解析以及内存分配回收操作。

深入分析与解决

根据以上两点问题分析的结论,我们进一步深入分析。

后端 upstream 响应拉长,最多可能影响 nginx 的处理能力。但是不可能会影响 nginx 内部模块占用过多的 cpu 操作。并且当时占用 cpu 高的模块,是在请求的时候才会走的逻辑。不太可能是 upstream 后端拖住 nginx,从而触发这个 cpu 的耗时操作。

遇到这种问题,我们优先解决已知的,并且非常明确的问题。那就是 cpu 高的问题。解决方式先降级关闭占用 cpu 过高的模块,然后进行观察。经过降级关闭该模块 cpu 降下来了,并且 nginx 请求流量也正常了。之所以会影响 upstream 时间拉长,因为 upstream 后端的服务调用的接口可能是个环路再次走回到 nginx。

最终解决方案:

  1. 更换 JSON 解析库:将当前使用的低性能 JSON 库替换为 libjson-c 或 rapidjson 等高性能库,减少 CPU 占用。
  2. 优化 Nginx 配置:调整 worker_processes 和 worker_connections,确保并发处理能力匹配流量需求。
  3. 排查上游链路:检查 upstream 后端是否存在死循环或数据库锁等待问题,避免请求回流。
  4. 添加熔断机制:在网关层增加超时控制和熔断策略,防止个别慢请求拖垮整个集群。

结语

运维排查问题不仅需要丰富的经验,更需要借助合适的工具。从基础的 top、vmstat 到高级的 perf、火焰图,每种工具都有其适用的场景。掌握这些工具并建立系统的分析方法论,能够显著提升故障定位效率,保障系统稳定性。

目录

  1. 背景
  2. 说明
  3. 分析问题的方法论
  4. CPU 分析
  5. 说明
  6. 分析工具
  7. 使用方式
  8. 查看系统 cpu 使用情况
  9. 查看所有 cpu 核信息
  10. 查看 cpu 使用情况以及平均负载
  11. 进程 cpu 的统计信息
  12. 跟踪进程内部函数级 cpu 使用情况
  13. 内存分析
  14. 说明
  15. 分析工具
  16. 使用方式
  17. 查看系统内存使用情况
  18. 虚拟内存统计信息
  19. 查看系统内存情况
  20. 1s 采集周期,获取内存的统计信息
  21. 查看进程的内存映像信息
  22. 检测程序内存问题
  23. 磁盘 IO 分析
  24. 说明
  25. 分析工具
  26. 使用方式
  27. 查看系统 io 信息
  28. 统计 io 详细信息
  29. 查看进程级 io 的信息
  30. 查看系统 IO 的请求
  31. 网络分析
  32. 说明
  33. 分析工具
  34. 使用方式
  35. 显示网络统计信息
  36. 显示当前 UDP 连接状况
  37. 显示 UDP 端口号的使用情况
  38. 统计机器中网络连接各个状态个数
  39. 显示 TCP 连接
  40. 显示 sockets 摘要信息
  41. 显示所有 udp sockets
  42. tcp,etcp 状态
  43. 查看网络 IO
  44. 抓包以包为单位进行输出
  45. 抓包以流为单位显示数据内容
  46. 系统负载分析
  47. 说明
  48. 分析工具
  49. 使用方式
  50. 查看负载情况
  51. 统计系统调用耗时情况
  52. 跟踪指定的系统操作例如 epoll_wait
  53. 查看内核日志信息
  54. 火焰图 (Flame Graph)
  55. 说明
  56. 安装依赖库
  57. 安装 systemtap,默认系统已安装
  58. 内核调试库必须跟内核版本对应,例如:uname -r 2.6.18-308.el5
  59. 安装内核调试库
  60. 安装 FlameGraph 工具
  61. CPU 级别火焰图
  62. on-CPU
  63. on-CPU user
  64. 进入结果目录
  65. on-CPU kernel
  66. 进入结果目录
  67. 开一个临时端口 8088
  68. 打开浏览器输入地址 127.0.0.1:8088/pid.svg
  69. off-CPU
  70. off-CPU user
  71. 进入结果目录
  72. off-CPU kernel
  73. 进入结果目录
  74. 开一个临时端口 8088
  75. 打开浏览器输入地址 127.0.0.1:8088/pid.svg
  76. 内存级别火焰图
  77. 进入结果目录
  78. 开一个临时端口 8088
  79. 打开浏览器输入地址 127.0.0.1:8088/pid.svg
  80. 性能回退 - 红蓝差分火焰图
  81. 抓取代码修改前的 profile 1 文件
  82. 抓取代码修改后的 profile 2 文件
  83. 生成差分火焰图
  84. 案例分析
  85. 接入层 nginx 集群异常现象
  86. 分析 nginx 相关指标
  87. 分析 nginx 请求流量
  88. 分析 nginx 响应时间
  89. 分析 nginx upstream 响应时间
  90. 分析系统 cpu 情况
  91. 通过 top 观察系统指标
  92. 分析 nginx 进程内部 cpu 情况
  93. 火焰图分析 cpu
  94. 生成用户态 cpu 火焰图
  95. on-CPU user
  96. 进入结果目录
  97. 开一个临时端口 8088
  98. 打开浏览器输入地址 127.0.0.1:8088/pid.svg
  99. 案例总结
  100. 深入分析与解决
  101. 结语
  • 💰 8折买阿里云服务器限时8折了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • 双指针算法实战:移动零与复写零详解
  • Python 终端播放网易云音乐工具 pyncm 使用指南
  • 25 个降低 AI 检测率提示词:角色设定与语义重构技巧
  • 无人机租赁平台功能与技术架构解析
  • BaseCTF Week3 Web 与杂项解题复盘
  • 从三年前端到 CS 硕士:韩国留学经历复盘与回归前端
  • 零基础转行学习Python指南与核心知识点梳理
  • Rust 异步 Web 框架 Axum:核心原理与实战进阶
  • 基于C++11手写Promise实现及与std::promise对比
  • ViewModel 中 StateFlow 与 SharedFlow 的使用建议及单元测试指南
  • SpringBoot 集成 RabbitMQ 常见消息模式示例
  • 深度生成模型对比:VAE、GAN、AR、Flow 与 Diffusion 原理及实现
  • ThreadLocal 原理、使用场景及内存泄漏问题详解
  • OpenClaw macOS 安装配置教程
  • 基于 Web 的工业设备监测系统架构设计:非功能需求与数据访问机制
  • CSS 背景样式详解:颜色、图片与定位
  • AI 绘画的商业应用、代码案例与版权探讨
  • C++ 继承进阶:友元、静态成员与菱形继承解析
  • 大模型提示词工程(Prompt Engineering)核心技巧与实践
  • C++ 继承基础:概念定义、访问权限与默认成员函数

相关免费在线工具

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online

  • JSON 压缩

    通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online

  • JSON美化和格式化

    将JSON字符串修饰为友好的可读格式。 在线工具,JSON美化和格式化在线工具,online