Linux 性能调优
大约 12 分钟约 3645 字
Linux 性能调优
简介
Linux 性能调优是一个系统性的工程,涵盖 CPU、内存、磁盘 I/O 和网络四个核心维度。性能问题的排查通常遵循"先测量,再分析,最后优化"的原则——不要盲目调参,而是通过数据定位瓶颈,然后针对性地进行优化。
掌握 top、vmstat、iostat、sar、perf 等性能分析工具,能够帮助运维人员和开发人员快速定位系统瓶颈。本文将从四个维度全面介绍 Linux 性能分析的方法、工具使用、参数调优和生产环境的最佳实践。
性能分析方法论
USE 方法(Utilization, Saturation, Errors)
USE 方法是 Brendan Gregg 提出的一种性能分析方法,针对每个资源检查三个指标:
| 指标 | 说明 | 命令示例 |
|---|---|---|
| Utilization(使用率) | 资源忙的时间百分比 | top, mpstat |
| Saturation(饱和度) | 资源排队等待的工作量 | vmstat(run queue), iostat(avgqu-sz) |
| Errors(错误数) | 错误事件数量 | dmesg, journalctl |
性能排查流程
1. 确认问题现象
└── 响应慢?CPU 高?内存溢出?磁盘满?
2. 系统级分析(宏观)
└── top / uptime / free / df / iostat
3. 进程级分析(微观)
└── pidstat / ps / lsof / strace
4. 内核级分析(深入)
└── perf / eBPF / flame graph
5. 针对性优化
└── 修改参数 / 优化代码 / 升级硬件CPU 分析
系统级 CPU 监控
# CPU 使用概况(一次性快照)
top -bn1 | head -20
# 每 1 秒采样,共 5 次
mpstat 1 5
# 查看 CPU 信息
lscpu | grep "CPU(s)"
cat /proc/cpuinfo | grep "model name" | head -1
# 查看每个 CPU 核心的使用率
mpstat -P ALL 1 5
# 查看系统负载
uptime
cat /proc/loadavg
# load average: 1.5, 1.2, 0.8
# 含义:1/5/15 分钟内运行队列中的平均进程数
# 负载 > CPU 核数 = 过载进程级 CPU 分析
# 每个进程的 CPU 使用率
pidstat -u 1 5
# CPU 使用率最高的 10 个进程
ps aux --sort=-%cpu | head -11
# 查看指定进程的 CPU 使用
pidstat -u -p <PID> 1 5
# 查看进程的线程 CPU 使用
pidstat -t -p <PID> 1 5
# 实时查看进程状态
top -p <PID>CPU 瓶颈判断
# 使用 vmstat 查看 CPU 状态
vmstat 1 5
# 关键列:
# us = 用户态 CPU 使用率
# sy = 内核态 CPU 使用率
# id = 空闲 CPU 使用率
# wa = I/O 等待(如果 wa 高,瓶颈在磁盘而非 CPU)
# st = 虚拟化偷取时间
# CPU 瓶颈特征:
# - load average > CPU 核数
# - us + sy 接近 100%
# - 运行队列(procs r)持续 > CPU 核数perf 高级分析
# 查看占用 CPU 最多的函数
perf top
# 记录指定进程的 CPU profile
perf record -g -p <PID> -- sleep 30
# 查看记录结果
perf report
# 生成火焰图(需要 FlameGraph 工具)
perf script | stackcollapse-perf.pl | flamegraph.pl > cpu_flamegraph.svg内存分析
系统级内存监控
# 内存使用概况
free -h
# total = used + free + buff/cache
# available = 实际可用的内存(含可回收的缓存)
# 详细内存信息
cat /proc/meminfo | head -20
vmstat 1 5
# 关键列:
# swpd = swap 使用量
# free = 空闲内存
# buff = 缓冲区
# cache = 缓存
# si/so = swap in/swap out(非零表示系统在使用 swap)
# 内核 slab 缓存
slabtop
# 内存映射
cat /proc/<PID>/maps
pmap -x <PID>进程级内存分析
# 按内存排序的进程列表
ps aux --sort=-%mem | head -11
# 查看进程的内存详情
pidstat -r 1 5
# 查看进程的内存映射
cat /proc/<PID>/status | grep -E "VmRSS|VmSize|VmSwap"
# 查看进程的内存分布
pmap -x <PID> | tail -1OOM 分析
# 查看 OOM Killer 日志
dmesg | grep -i "oom"
journalctl -k | grep -i "oom"
# 查看被 OOM Kill 的进程
grep "Out of memory" /var/log/messages
# 查看进程的 OOM Score(分数越高越容易被杀)
cat /proc/<PID>/oom_score
# 调整进程的 OOM 权重(-1000 = 永远不被杀)
echo -1000 > /proc/<PID>/oom_score_adj
# 内存缓存清理(谨慎使用!)
# 1 = 释放页缓存
# 2 = 释放 dentry 和 inode 缓存
# 3 = 释放所有缓存
sync && echo 3 > /proc/sys/vm/drop_cachesSwap 分析
# 查看 swap 使用情况
swapon --show
free -h
# 查看 swap 使用最多的进程
for file in /proc/*/status; do
awk '/VmSwap|Name/{printf $2 " " $3}END{print ""}' "$file"
done | sort -k 2 -n -r | head -10
# 禁用 swap(有风险!)
swapoff -a
# 调整 swap 使用倾向
sysctl vm.swappiness=10磁盘 I/O 分析
系统级 I/O 监控
# I/O 统计(每秒刷新)
iostat -xz 1 5
# 关键列:
# %util = 设备利用率(接近 100% 表示磁盘饱和)
# await = 平均 I/O 等待时间(ms)
# r_await / w_await = 读/写平均等待时间
# avgqu-sz = 平均队列长度
# 实时 I/O 最高的进程
iotop -o
# 磁盘使用情况
df -h
# 目录大小
du -sh /var/log/*
du -sh /data/*
# 查看 I/O 调度器
cat /sys/block/sda/queue/scheduler
# 可选:noop / deadline / cfq / mq-deadline / bfq进程级 I/O 分析
# 查看进程的 I/O 统计
pidstat -d 1 5
# 查看进程打开的文件
lsof -p <PID>
# 查看进程在哪个文件上执行 I/O
iotop -p <PID>
# 使用 strace 跟踪进程的系统调用
strace -p <PID> -e trace=read,write,open,statI/O 调度器选择
# 查看当前 I/O 调度器
cat /sys/block/sdX/queue/scheduler
# 临时修改调度器
echo cfq > /sys/block/sdX/queue/scheduler
# 推荐:
# SSD / NVMe → noop 或 mq-deadline
# HDD → bfq 或 cfq
# 虚拟机 → noop网络分析
网络流量监控
# 网络流量统计(每秒)
sar -n DEV 1 5
# 关键列:
# rxkB/s = 每秒接收 KB
# txkB/s = 每秒发送 KB
# rxpck/s = 每秒接收包数
# txpck/s = 每秒发送包数
# Socket 统计
ss -s
# 查看所有 TCP 连接
ss -tan
# 查看连接状态分布
ss -tan | awk '{print $1}' | sort | uniq -c | sort -rn
# 按进程查看网络流量
nethogs网络连接分析
# 查看监听端口
ss -tlnp
# 查看指定端口的连接
ss -tnp | grep :80
# 查看所有 ESTABLISHED 连接
ss -tan state established
# 查看连接数最多的 IP
ss -tan | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -rn | head -10
# 查看连接队列
netstat -s | grep -i "overflow"
ss -lnt | grep -i "Recv-Q\|Send-Q"网络排障
# 连通性测试
ping -c 4 8.8.8.8
mtr --report example.com
# 路由追踪
traceroute example.com
# DNS 排查
dig example.com
nslookup example.com
host example.com
# 抓包分析
tcpdump -i eth0 port 80 -nn
tcpdump -i eth0 host 192.168.1.1 -w capture.pcap
tcpdump -i eth0 'tcp[tcpflags] & tcp-syn != 0' # 只抓 SYN 包
# 连接跟踪
conntrack -L
conntrack -C内核参数调优
综合调优配置
# /etc/sysctl.d/99-performance.conf
# ========== 网络 ==========
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 65535
net.ipv4.tcp_tw_reuse = 1
net.ipv4.ip_local_port_range = 1024 65535
net.core.netdev_max_backlog = 65535
net.ipv4.tcp_keepalive_time = 600
net.ipv4.tcp_fin_timeout = 15
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.core.default_qdisc = fq
net.ipv4.tcp_congestion_control = bbr
# ========== 内存 ==========
vm.swappiness = 10
vm.overcommit_memory = 1
vm.max_map_count = 262144
vm.dirty_ratio = 15
vm.dirty_background_ratio = 5
# ========== 文件描述符 ==========
fs.file-max = 1048576
fs.nr_open = 1048576
# ========== 应用 ==========
sysctl -p /etc/sysctl.d/99-performance.conf文件描述符限制
# /etc/security/limits.conf
* soft nofile 65535
* hard nofile 65535
* soft nproc 65535
* hard nproc 65535
# 验证
ulimit -n
ulimit -u监控告警建议
告警阈值
| 指标 | 告警阈值 | 严重阈值 |
|---|---|---|
| CPU 使用率 | > 80% | > 95% |
| 内存使用率 | > 85% | > 95% |
| 磁盘使用率 | > 80% | > 90% |
| 磁盘 I/O await | > 20ms | > 50ms |
| %util | > 70% | > 90% |
| Swap 使用 | > 100MB | > 1GB |
| 网络丢包率 | > 1% | > 5% |
| TCP 连接数 | 接近上限 | 超过上限 80% |
监控脚本示例
#!/bin/bash
# /opt/scripts/health_check.sh
set -euo pipefail
WARN=80
CRIT=95
check_cpu() {
local usage=$(top -bn1 | grep "Cpu(s)" | awk '{print $2}' | cut -d. -f1)
if [ "$usage" -gt "$CRIT" ]; then
echo "[CRITICAL] CPU: ${usage}%"
elif [ "$usage" -gt "$WARN" ]; then
echo "[WARNING] CPU: ${usage}%"
fi
}
check_memory() {
local usage=$(free | awk '/Mem/{printf "%.0f", $3/$2*100}')
if [ "$usage" -gt "$CRIT" ]; then
echo "[CRITICAL] Memory: ${usage}%"
elif [ "$usage" -gt "$WARN" ]; then
echo "[WARNING] Memory: ${usage}%"
fi
}
check_disk() {
while read -r line; do
local usage=$(echo "$line" | awk '{print $5}' | cut -d% -f1)
local mount=$(echo "$line" | awk '{print $6}')
if [ "$usage" -gt "$CRIT" ]; then
echo "[CRITICAL] Disk ${mount}: ${usage}%"
elif [ "$usage" -gt "$WARN" ]; then
echo "[WARNING] Disk ${mount}: ${usage}%"
fi
done < <(df -h | awk 'NR>1')
}
check_cpu
check_memory
check_diskeBPF 高级性能分析
eBPF(Extended Berkeley Packet Filter)是现代 Linux 内核的高级可观测性技术,可以在内核中安全地运行沙箱程序,实现零开销的性能追踪。
# 安装 bcc 工具集(CentOS 7/8)
yum install -y bcc-tools
# 工具路径:/usr/share/bcc/tools/
# ========== CPU 分析 ==========
# 查看函数调用频率和延迟
/usr/share/bcc/tools/funclatency -p <PID> do_sys_open
# 查看进程的 on-CPU 时间分布
/usr/share/bcc/tools/offcputime -p <PID> 5
# 查看进程调度延迟
/usr/share/bcc/tools/runqlat 1 10
# ========== 内存分析 ==========
# 跟踪内存分配
/usr/share/bcc/tools/memleak -p <PID>
# 跟踪页面错误
/usr/share/bcc/tools/faults 1 10
# 查看 slab 缓存分配
/usr/share/bcc/tools/slabratetop 1 10
# ========== 磁盘 I/O 分析 ==========
# 跟踪块设备 I/O 延迟
/usr/share/bcc/tools/biolatency 1 10
# 实时显示磁盘 I/O
/usr/share/bcc/tools/biosnoop
# 按 PID 汇总 I/O 大小
/usr/share/bcc/tools/bitesize 1 10
# ========== 网络分析 ==========
# 跟踪 TCP 连接建立
/usr/share/bcc/tools/tcpconnect
# 跟踪 TCP 重传
/usr/share/bcc/tools/tcpretrans
# 按 PID 汇总网络流量
/usr/share/bcc/tools/nettopJava 应用性能分析
# ========== JVM 进程识别 ==========
# 查找 Java 进程
jps -lv
ps aux | grep java
# ========== 线程分析 ==========
# 查看 Java 进程的线程栈
jstack <PID>
jstack -l <PID> > thread_dump.txt
# 查看最耗 CPU 的线程
# 步骤1:找到 CPU 最高的 Java 进程
top -bn1 -H | head -20
# 步骤2:将线程 ID 转为十六进制
printf "%x\n" <TID>
# 步骤3:在 jstack 输出中搜索该线程
jstack <PID> | grep -A 30 "<HEX_TID>"
# ========== 内存分析 ==========
# 查看堆内存概况
jmap -heap <PID>
# 生成堆转储(用于 MAT 分析)
jmap -dump:format=b,file=heap.hprof <PID>
# 查看对象统计
jmap -histo <PID> | head -30
# ========== GC 分析 ==========
# 查看 GC 统计
jstat -gc <PID> 1000 10
# 关键列:YGC(年轻代GC次数)、YGCT(年轻代GC时间)、FGC(Full GC次数)、FGCT(Full GC时间)
# ========== JFR(Java Flight Recorder)==========
# 启动 JFR 录制
jcmd <PID> JFR.start duration=60s filename=recording.jfr
# 分析 jfr 文件可使用 JDK Mission Control 工具Nginx 性能调优
# /etc/nginx/nginx.conf 性能优化配置
worker_processes auto; # 自动匹配 CPU 核数
worker_cpu_affinity auto; # 自动绑定 CPU 亲和性
worker_rlimit_nofile 65535; # worker 进程最大文件描述符
events {
worker_connections 4096; # 每个 worker 的最大连接数
use epoll; # Linux 使用 epoll
multi_accept on; # 一次性接受所有新连接
accept_mutex off; # 高并发场景关闭互斥锁
}
http {
# ========== 连接优化 ==========
sendfile on; # 零拷贝发送文件
tcp_nopush on; # 优化数据包发送
tcp_nodelay on; # 禁用 Nagle 算法
keepalive_timeout 65; # 长连接超时
keepalive_requests 10000; # 每个长连接最大请求数
# ========== 缓冲区优化 ==========
client_body_buffer_size 16K;
client_header_buffer_size 1k;
client_max_body_size 50m;
large_client_header_buffers 4 8k;
# ========== Gzip 压缩 ==========
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 4; # 压缩级别 1-9,4 是性价比最优
gzip_min_length 1024; # 大于 1KB 才压缩
gzip_types
text/plain
text/css
application/json
application/javascript
text/xml
application/xml
application/xml+rss
text/javascript;
# ========== FastCGI 优化(配合 PHP) ==========
fastcgi_buffers 8 16k;
fastcgi_buffer_size 32k;
fastcgi_connect_timeout 300;
fastcgi_send_timeout 300;
fastcgi_read_timeout 300;
# ========== 代理缓冲(反向代理时) ==========
proxy_buffer_size 8k;
proxy_buffers 8 16k;
proxy_busy_buffers_size 32k;
# ========== Open file cache ==========
open_file_cache max=65535 inactive=20s;
open_file_cache_valid 30s;
open_file_cache_min_uses 2;
open_file_cache_errors on;
# ========== 日志优化 ==========
access_log off; # 高并发场景关闭访问日志
# 或者使用缓冲写入
# access_log /var/log/nginx/access.log buffer=32k flush=5m;
}MySQL 性能调优
# ========== 关键参数(/etc/my.cnf) ==========
# InnoDB 缓冲池大小(通常设为物理内存的 60-80%)
innodb_buffer_pool_size = 4G
# 日志文件大小(影响写入性能和崩溃恢复时间)
innodb_log_file_size = 512M
# 刷新策略
# 0 = 每秒刷新(性能最好,可能丢 1 秒数据)
# 1 = 每次提交刷新(最安全,性能最差)
# 2 = 每次提交写日志,每秒刷新(折中方案)
innodb_flush_log_at_trx_commit = 2
# 并发线程数
innodb_thread_concurrency = 0 # 0 = 不限制(推荐)
# I/O 容量
innodb_io_capacity = 2000 # SSD 建议 2000-5000
innodb_io_capacity_max = 4000
# 查询缓存(MySQL 8.0 已移除,因为高并发下性能反而下降)
# query_cache_size = 0
# query_cache_type = 0
# 连接数
max_connections = 500
back_log = 512
# 排序和连接缓冲
sort_buffer_size = 2M
join_buffer_size = 2M
read_buffer_size = 2M
read_rnd_buffer_size = 4M
# ========== 慢查询分析 ==========
# 开启慢查询日志
slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 1 # 超过 1 秒的查询
log_queries_not_using_indexes = 1 # 记录未使用索引的查询
# 分析慢查询
mysqldumpslow -s t -t 10 /var/log/mysql/slow.log
# EXPLAIN 分析查询计划
# EXPLAIN SELECT * FROM orders WHERE user_id = 123;
# EXPLAIN FORMAT=JSON SELECT ...; # 更详细的输出
# ========== 实时监控 ==========
# 查看当前正在执行的查询
mysql -e "SHOW PROCESSLIST"
mysql -e "SHOW ENGINE INNODB STATUS\G"
# 查看 InnoDB 状态
mysqladmin -r -i 1 ext | awk '/Innodb_rows_read/{delta=$NF}END{print delta}'系统启动与服务优化
# ========== 开机启动优化 ==========
# 查看开机耗时分析
systemd-analyze
systemd-analyze blame # 查看每个服务启动耗时
systemd-analyze critical-chain # 查看关键启动链
# 禁用不需要的服务
systemctl disable avahi-daemon
systemctl disable bluetooth
systemctl disable cups
systemctl disable ModemManager
# ========== CPU 调度优化 ==========
# 查看 CPU 频率策略
cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
# 设置为性能模式(服务器推荐)
cpupower frequency-set -g performance
# 或针对每个核心
for i in /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor; do
echo performance > "$i"
done
# ========== NUMA 优化 ==========
# 查看 NUMA 拓扑
numactl --hardware
numastat
# 绑定进程到 NUMA 节点(减少跨节点内存访问延迟)
numactl --cpunodebind=0 --membind=0 java -jar app.jar
# ========== 大页内存(HugePages)==========
# 适用于数据库、Java 等大内存应用
# 查看当前大页配置
cat /proc/meminfo | grep Huge
# 配置大页(2MB 页面)
echo 1024 > /proc/sys/vm/nr_hugepages # 分配 1024 个 2MB 大页 = 2GB
# 永久配置
echo "vm.nr_hugepages = 1024" >> /etc/sysctl.d/99-performance.conf火焰图生成与分析
# ========== 安装 FlameGraph 工具 ==========
git clone https://github.com/brendangregg/FlameGraph /opt/FlameGraph
# ========== CPU 火焰图 ==========
# 使用 perf 采样
perf record -F 99 -a -g -- sleep 30
perf script | /opt/FlameGraph/stackcollapse-perf.pl | /opt/FlameGraph/flamegraph.pl > cpu.svg
# ========== Off-CPU 火焰图 ==========
# 分析进程等待 CPU 的时间
perf record -e sched:sched_stat_sleep -e sched:sched_switch -a -g -- sleep 30
perf script | /opt/FlameGraph/stackcollapse-perf.pl | /opt/FlameGraph/flamegraph.pl > offcpu.svg
# ========== 内存火焰图 ==========
# 使用 bcc 工具跟踪内存分配
/usr/share/bcc/tools/memleak -p <PID> -T 5 > memleak.txt
# ========== 火焰图解读技巧 ==========
# 1. x 轴 = 采样比例(不是时间),越宽的函数越耗时
# 2. y 轴 = 调用栈深度
# 3. 顶部平坦区域 = 性能热点
# 4. 关注你自己的代码栈帧,忽略系统调用
# 5. SVG 可点击放大特定函数容器化环境的性能考量
# ========== Docker 容器资源限制 ==========
# 限制 CPU 和内存
docker run -d \
--cpus="2.0" \
--memory="4g" \
--memory-swap="4g" \
--memory-reservation="3g" \
--pids-limit=1000 \
nginx
# 查看容器资源使用
docker stats
docker stats --no-stream <容器名>
# ========== cgroup v2 资源监控 ==========
# 查看容器的 cgroup 路径
cat /proc/<PID>/cgroup
# 查看 CPU 使用限制
cat /sys/fs/cgroup/docker/<容器ID>/cpu.max
# 查看 CPU 使用统计
cat /sys/fs/cgroup/docker/<容器ID>/cpu.stat
# 查看内存限制和使用
cat /sys/fs/cgroup/docker/<容器ID>/memory.max
cat /sys/fs/cgroup/docker/<容器ID>/memory.current
cat /sys/fs/cgroup/docker/<容器ID>/memory.peak
# ========== Kubernetes Pod 性能分析 ==========
# 在 Pod 内执行性能分析
kubectl top pods -n <namespace>
kubectl top nodes
# 查看 Pod 资源限制
kubectl get pod <pod-name> -o jsonpath='{.spec.containers[*].resources}'
# 进入 Pod 执行命令
kubectl exec -it <pod-name> -- top -bn1
kubectl exec -it <pod-name> -- free -h常见性能问题速查表
问题现象 可能原因 排查命令
--------------------------------------------------------------------------------------------
系统响应缓慢 CPU 过载 top, uptime, vmstat
内存不足 free, vmstat(si/so)
磁盘 I/O 饱和 iostat(%util), iotop
网络拥塞 sar -n DEV, tcpdump
CPU us 高 用户态代码密集 perf top, 火焰图
CPU sy 高 系统调用频繁 strace -c, perf
CPU wa 高 I/O 等待 iostat, pidstat -d
CPU st 高 虚拟化资源争抢 联系云厂商或调整 VM 配置
内存持续增长 内存泄漏 valgrind, pmap, smem
Swap 使用高 物理内存不足 free, vmstat, top
OOM Kill 内存超限 dmesg, /var/log/messages
磁盘 await 高 磁盘性能瓶颈 iostat, iotop
磁盘 %util 高 I/O 负载过重 iostat, 考虑 SSD 升级
文件系统满 日志/数据未清理 df -h, du -sh
网络延迟高 带宽不足/路由问题 mtr, traceroute, ping
连接超时 连接队列满 ss -lnt, netstat -s
丢包 网络设备/MTU 问题 ifconfig, ip -s link
DNS 解析慢 DNS 服务器响应慢 dig, nslookup