引言
Linux服务器性能问题是最让运维工程师头疼的故障之一。服务器响应缓慢、网站打开转圈、数据库查询超时,这些现象背后可能隐藏着CPU打满、内存泄漏、磁盘IO瓶颈、网络延迟等各种原因。不同于服务不可用这种"非黑即白"的故障,性能问题往往是渐进的、模糊的,需要运维工程师有系统的排查思路和丰富的经验积累。
本文面向初中级运维工程师和系统管理员,详细讲解Linux服务器性能问题的排查流程。文章不追求面面俱到的理论讲解,而是从实战出发,提供可以直接落地执行的操作步骤。内容包括CPU、内存、磁盘IO、网络四大基础资源的排查方法,进程级别性能分析工具的使用,以及常见性能瓶颈的识别和处理。
本文假设读者具备基本的Linux操作能力,能够熟练使用top、ps等基础命令。阅读本文后,读者应该能够:对性能问题建立系统化的排查思路、使用top、htop、vmstat、iostat、netstat等工具进行性能诊断、分析CPU、内存、磁盘、网络四大资源的瓶颈所在、定位到具体进程或服务并进行处理。
一、性能排查基础
1.1 性能问题的分类
Linux服务器性能问题可以分为四大类:CPU密集型、内存密集型、IO密集型、网络密集型。实际生产环境中,往往是多种问题混合存在,需要综合分析。
CPU密集型问题的特征是服务器负载高但IO等待低。典型场景包括:频繁的计算任务、加密解密、大量正则表达式处理、不当的循环结构等。这类问题的表现是CPU使用率接近100%,但磁盘和网络IO较低。
内存密集型问题的特征是可用内存持续下降,swap使用率上升。典型场景包括:内存泄漏、应用配置不当(jvm heap过大)、缓存数据过大等。表现是free命令显示可用内存很少,si/so(swap in/out)数值较高。
IO密集型问题的特征是磁盘读写量巨大,IO等待时间长。典型场景包括:频繁的日志写入、大数据量的数据库操作、不当的临时文件使用等。表现是iostat显示高util%,CPU的wa(wait)值高。
网络密集型问题的特征是网络带宽接近饱和或存在大量连接异常。典型场景包括:DDoS攻击、爬虫频繁访问、接口调用超时等。表现是网络流量接近带宽上限、大量连接处于TIME_WAIT状态。
1.2 排查的基本顺序
性能问题排查遵循"先整体后局部、先CPU后内存、IO网络配合看"的原则。
第一步,用top或uptime命令快速了解系统负载概况。系统负载(load average)如果超过CPU核心数,说明存在资源争抢。
第二步,用vmstat命令查看系统整体的CPU、内存、IO、swap状态。关注r(运行队列长度)、b(阻塞进程数)、wa(IO等待)、si/so(swap换入换出)等指标。
第三步,用iostat命令查看磁盘IO情况,确定是否存在IO瓶颈。
第四步,用free命令查看内存使用情况,确认是否存在内存不足。
第五步,用netstat或ss命令查看网络连接状态,确认是否存在网络问题。
第六步,确定瓶颈所在后,用top、ps等工具定位到具体进程,进行进一步分析。
1.3 系统负载与CPU核心数的关系
理解系统负载(load average)与CPU核心数的关系,是判断服务器是否"繁忙"的前提。
load average是Linux系统的重要指标,通过uptime命令或top命令的第一行可以看到:
uptime # 输出:1612 up 45 days, 3:22, 2 users, load average: 2.85, 3.21, 4.10
load average的三个数字分别代表1分钟、5分钟、15分钟的平均负载。理想情况下,load average应该小于CPU核心数。如果load average长期高于CPU核心数,说明系统处于高负载状态,新任务需要等待才能执行。
假设服务器有8个CPU核心:
load average为2.85,说明平均有2.85个任务在等待CPU资源,系统比较轻松
load average为8,说明CPU资源刚好够用,没有等待
load average为12,说明有4个任务在等待CPU资源,系统繁忙
可以通过以下命令查看CPU核心数:
nproc # 或者 grep "processor" /proc/cpuinfo | wc -l
1.4 关键性能指标速览
vmstat命令是性能排查中最常用的工具之一,它能在一屏之内展示系统整体的CPU、内存、IO、swap等关键指标:
vmstat 2 5
参数2表示每隔2秒采样一次,共采样5次。输出示例:
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- r b swpd free buff cache si so bi bo in cs us sy id wa st 2 0 0 2048000 123456 789012 0 0 50 100 500 1000 10 5 80 5 0
各列含义:
r:运行队列中的进程数,表示等待CPU的进程数
b:阻塞的进程数,表示等待IO或资源的进程数
swpd:使用的swap空间大小(KB)
free:可用内存大小(KB)
buff:用作缓冲的内存大小(KB)
cache:用作缓存的内存大小(KB)
si:每秒从swap换入的内存大小(KB)
so:每秒换出到swap的内存大小(KB)
bi:每秒从块设备接收的块数(blocks/s)
bo:每秒发送到块设备的块数(blocks/s)
in:每秒中断数
cs:每秒上下文切换次数
us:用户空间CPU使用率
sy:内核空间CPU使用率
id:空闲率
wa:等待IO的CPU时间百分比
st:被虚拟机偷走的CPU时间百分比
正常状态参考:
r值应小于CPU核心数的4倍
b值应接近0
si/so应接近0(持续不为0说明内存不足)
id应大于30%(如果持续低于30%说明CPU繁忙)
wa应小于20%(如果高于20%说明IO存在瓶颈)
二、CPU性能排查
2.1 快速查看CPU状态
top命令是排查CPU问题的首选工具,它能够实时显示系统资源使用情况和进程列表:
top
top界面的第一行是系统负载信息,第二行是任务(进程)统计,第三行是CPU使用情况,第四五行是内存使用情况,下方是进程列表。
CPU区域的显示含义:
%Cpu(s): 25.0 us, 5.0 sy, 0.0 ni, 68.0 id, 2.0 wa, 0.0 hi, 0.0 si, 0.0 st
us(user):用户空间进程消耗的CPU百分比
sy(system):内核空间消耗的CPU百分比
ni(nice):优先级调整过的用户进程消耗的CPU百分比
id(idle):空闲CPU百分比
wa(wait):等待IO的CPU百分比
hi(hardirq):处理硬件中断消耗的CPU百分比
si(softirq):处理软中断消耗的CPU百分比
st(steal):被虚拟机偷走的CPU百分比
us高sy低:正常情况,说明用户进程在大量计算。
us高sy也高:需要检查系统调用或上下文切换是否过多。
wa高:说明进程在等待IO,可能是磁盘IO慢或网络IO慢。
hi/si高:说明存在大量中断或软中断,可能与网络或存储驱动有关。
2.2 定位CPU占用最高的进程
在top界面中,按Shift+M按内存排序,按Shift+P按CPU排序。按q退出。
查看CPU占用最高的进程:
ps aux --sort=-%cpu | head -20
这条命令会列出CPU占用前20的进程。输出示例:
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 12345 95.0 2.0 1234567 456789 ? R 10:00 950:00 myapp root 12346 3.2 1.0 234567 123456 ? S 10:00 120:00 java root 1 0.5 0.1 12345 6789 ? Ss Jan01 5:00 systemd
%CPU列是重点,如果某个进程的CPU占用持续接近或超过100%(单核心),说明该进程存在CPU密集型问题。
2.3 查看进程线程
对于Java、Go等支持多线程的语言,一个进程可能有多个线程。查看特定进程的线程:
# 查看进程的所有线程 ps -eLf | grep# 或使用top查看线程 top -H -p
top的-H参数显示线程视图,-p参数指定进程ID。
2.4 分析CPU使用率高的常见原因
原因一:业务代码存在无限循环或密集计算。这是最常见的原因,需要检查业务代码逻辑。
排查方法:使用strace跟踪系统调用,确认进程在做什么:
strace -p-c
-c参数统计系统调用,按Ctrl+C结束。
原因二:GC(垃圾回收)频繁。对于Java应用,GC频繁会导致CPU飙高。
排查方法:查看GC日志,确认GC频率和耗时:
jstat -gc1000 10
这条命令每1秒打印一次GC统计,共打印10次。
原因三:正则表达式回溯。大量使用正则表达式的应用,如果正则写的不当,可能导致灾难性回溯。
原因四:加密解密或压缩解压。这些操作本身就是CPU密集型的,需要确认是否有必要。
2.5 高CPU问题的处理步骤
确认是高CPU问题后,按以下步骤处理:
第一步,确认是哪个进程:
ps aux --sort=-%cpu | head -10
第二步,查看该进程的详细信息:
ps -ef | grep
第三步,查看进程打开的文件和网络连接:
lsof -p
第四步,如果是业务进程,查看应用日志:
# Java应用 tail -f /var/log/myapp/application.log # Nginx tail -f /var/log/nginx/error.log
第五步,考虑处理措施:
如果是异常进程(如被入侵),立即kill:
kill -9
如果是业务进程存在bug,尝试重启或回滚
如果是配置不当,调整配置参数
如果是资源不足,考虑扩容
2.6 系统层面的CPU优化
如果确认是系统层面需要优化,考虑以下方向:
调整进程优先级。使用nice和renice调整进程优先级:
# 启动时设置优先级 nice -n 10 /path/to/application # 调整运行中的进程 renice -n 10 -p
nice值范围是-20到19,值越低优先级越高。
绑定CPU核心。使用taskset将进程绑定到特定CPU核心,减少上下文切换:
# 绑定到CPU核心0-3 taskset -c 0-3 -p
三、内存性能排查
3.1 快速查看内存状态
free命令是最常用的内存查看工具:
free -h
输出示例:
total used free shared buff/cache available Mem: 31Gi 28Gi 1.5Gi 200Mi 1.5Gi 2.5Gi Swap: 8Gi 0B 8Gi
各列含义:
total:总内存
used:已使用内存
free:完全未使用的内存
shared:共享内存(tmpfs)
buff/cache:缓冲和缓存(可以回收)
available:实际可用内存(包括cache可回收部分)
重点关注available而不是free。Linux会使用空闲内存作为缓存来提高性能,这些缓存可以在需要时释放。所以看到free很低但available很高是正常现象。
3.2 内存使用的详细分析
查看内存使用的详细信息:
cat /proc/meminfo
输出中关键指标:
MemTotal: 32768000 kB # 总内存 MemFree: 1500000 kB # 完全空闲 MemAvailable: 2500000 kB # 可用内存 Buffers: 123456 kB # 缓冲区 Cached: 1500000 kB # 缓存 SwapCached: 0 kB # 交换到磁盘的缓存 Active(anon): 18000000 kB # 活跃匿名内存 Inactive(anon): 2000000 kB # 不活跃匿名内存 Active(file): 5000000 kB # 活跃文件内存 Inactive(file): 3000000 kB # 不活跃文件内存 SwapTotal: 8000000 kB # swap总大小 SwapFree: 8000000 kB # swap空闲
SwapUsed不为0且持续增长,说明存在内存压力,物理内存不足。
3.3 查看进程内存占用
按内存使用排序查看进程:
ps aux --sort=-%mem | head -20
或者使用top按内存排序(按Shift+M)。
3.4 分析内存泄漏
内存泄漏的典型特征是:进程占用的内存持续增长,不下降,即使在负载降低后也不释放。
监控进程内存使用变化:
# 每5秒检查一次,共检查20次
for i in {1..20}; do
ps -o pid,rss,vsz,comm -p
sleep 5
done
或者使用pmap查看进程的内存映射:
pmap -x| sort -k3 -n -r | head -20
-x参数显示扩展格式,| sort按第3列(Kbytes)排序。
3.5 内存使用率高常见原因
原因一:应用内存泄漏。Java应用最常见,典型表现是堆内存持续增长直到OOM。
排查方法:分析堆内存dump或GC日志。Java应用可以查看JVM内存使用:
jstat -gcjmap -heap
原因二:缓存数据过大。Nginx、Redis等应用会使用大量内存作为缓存。
排查方法:检查应用配置,确认缓存大小限制。
原因三:JVM heap配置过大。如果JVM的heap配置超过了物理内存的一半,可能影响系统稳定性。
排查方法:检查JVM参数:
jcmdVM.flags
原因四:进程数过多。大量进程同时运行会消耗大量内存。
排查方法:检查进程数:
ps aux | wc -l
3.6 swap问题排查
swap使用率高(si/so持续不为0)是内存不足的明确信号。
查看swap使用情况:
swapon -s free -h vmstat 2 5
如果发现swap使用率高,需要分析是物理内存真的不足,还是存在内存泄漏。
分析哪些进程在使用swap:
for f in $(ls /proc/*/status 2>/dev/null); do
awk '/VmSwap/{print $2, $3, $4}' $f | while read size unit name; do
if [ "${size%"*}" -gt 0 ]; then
echo "$name $size $unit"
fi
done
done | sort -k2 -n -r | head -20
这个脚本会列出使用swap最多的前20个进程。
3.7 内存问题的处理步骤
第一步,确认是否真的内存不足:
free -h vmstat 2 5
如果available远大于used,说明内存充足,不需要处理。
第二步,确认是哪个进程占用内存最多:
ps aux --sort=-%mem | head -10
第三步,分析进程类型:
系统进程(kswapd、jbd2等)占用高,说明存在IO压力
业务进程占用高,分析应用日志和配置
多个进程占用都高,说明整体内存配置不足
第四步,处理措施:
调整应用内存配置(如JVM heap大小)
清理不必要的进程
增加物理内存
优化应用内存使用
四、磁盘IO排查
4.1 IO性能基础概念
磁盘IO问题是生产环境中常见的性能瓶颈。理解几个基本概念有助于后续排查:
IOPS(Input/Output Operations Per Second):每秒IO操作数,衡量随机读写能力。
吞吐量(Throughput):每秒数据传输量,衡量顺序读写能力,单位通常是MB/s或GB/s。
延迟(Latency):单个IO操作的响应时间,单位通常是毫秒。
利用率(Utilization):磁盘处理IO的时间占总时间的百分比,接近100%时说明磁盘饱和。
不同类型的存储设备性能差异巨大:
HDD(机械硬盘):IOPS通常几十到几百,延迟毫秒级
SATA SSD:IOPS通常几万,延迟亚毫秒级
NVMe SSD:IOPS可达几十万,延迟微秒级
4.2 iostat命令详解
iostat是排查磁盘IO问题的核心工具,需要安装sysstat包:
yum install sysstat # CentOS/RHEL apt-get install sysstat # Debian/Ubuntu
基本用法:
iostat -x 2 5
参数-x显示扩展统计信息,每2秒采样一次,共5次。
输出示例:
Linux 5.4.0-xxx (hostname) 05/13/2026 _x86_64_ (8 CPU) avg-cpu: %user %nice %system %iostat %idle 10.50 0.00 5.25 2.50 81.75 Device: r/s w/s rkB/s wkB/s rrqm/s wrqm/s %rrqm %wrqm r_await w_await aqu-sz %util sda 10.00 100.00 5120.00 51200.00 0.00 5.00 0.00 4.76 10.00 5.00 2.50 55.00
关键指标:
r/s、w/s:每秒读写次数
rkB/s、wkB/s:每秒读写数据量
await:平均IO等待时间(毫秒),包含排队时间和实际处理时间
%util:设备利用率,接近100%说明设备饱和
aqu-sz:平均等待中的IO请求数
判断IO瓶颈的标准:
%util接近100%:设备饱和
await远高于正常值(HDD通常10-20ms,SSD<1ms)
avgqu-sz持续大于1(对于单盘)
4.3 查看具体进程的IO使用
iotop命令可以查看每个进程的IO使用情况,需要root权限:
yum install iotop # 安装 iotop
iotop界面类似于top,按IO排序显示进程。
参数说明:
iotop -o # 只显示有IO活动的进程 iotop -p# 只显示特定进程 iotop -a # 累计显示IO量
如果iotop不可用,可以使用pidstat:
pidstat -d 2 5
4.4 查看IO等待
CPU的wa(wait)值高,说明进程在等待IO:
vmstat 2 5
结合iostat可以确认是哪个设备导致的IO等待。
4.5 分析IO模式
确认是IO问题后,需要分析是读多还是写多,是随机IO还是顺序IO。
查看每个磁盘的读写统计:
iostat -x 1 3
如果r/s高说明读多,w/s高说明写多。
查看具体文件系统的IO:
df -h
确认是哪个挂载点的问题。
4.6 常见IO问题原因
原因一:日志写入过多。应用程序产生大量日志写入。
排查方法:检查/var/log目录大小:
du -sh /var/log/*
原因二:数据库IO压力大。频繁的数据库读写操作。
排查方法:查看数据库的慢查询日志。
原因三:临时文件操作频繁。应用在/tmp目录频繁读写。
排查方法:使用lsof查看进程打开的文件。
原因四:swap操作。内存不足导致频繁换页。
排查方法:结合内存排查一起看。
4.7 IO问题的处理步骤
第一步,确认是否是IO问题:
iostat -x 2 5
关注%util和await指标。
第二步,如果是IO问题,确认是读还是写导致的:
iostat -x 1 3
看r/s和w/s哪个更高。
第三步,定位到具体进程:
iotop
第四步,分析是哪个文件或挂载点:
lsof -p
第五步,处理措施:
减少不必要的IO操作
优化应用IO模式(异步IO、合并写操作)
使用更快的存储设备
增加内存减少swap使用
清理不必要的文件
五、网络性能排查
5.1 快速查看网络状态
查看网络连接统计:
netstat -s
或者使用ss命令(更现代,性能更好):
ss -s
查看活动连接:
ss -tan state established | head -20
5.2 网络带宽检查
查看网卡流量:
cat /proc/net/dev
或者使用iftop(需要安装):
iftop -i eth0
监控特定端口的连接数:
netstat -an | grep :80 | wc -l
5.3 连接状态分析
分析TCP连接状态分布:
netstat -an | awk '/^tcp/{print $NF}' | sort | uniq -c
或使用ss命令:
ss -tan state established | wc -l ss -tan state time-wait | wc -l ss -tan state syn-recv | wc -l
常见的异常状态:
大量TIME_WAIT:可能是频繁建立和关闭连接
大量SYN_RECV:可能是SYN Flood攻击
大量ESTABLISHED但没有数据传输:可能是连接泄漏
5.4 网络延迟排查
测试到目标主机的延迟:
ping -c 10
测试DNS解析:
time nslookup example.com
测试TCP连接延迟:
telnet
5.5 网卡队列和中断
查看网卡中断分布:
cat /proc/interrupts | grep eth
查看网卡队列:
ethtool -l eth0
调整网卡队列数:
ethtool -L eth0 combined 8
5.6 网络问题的处理步骤
第一步,确认是否网络问题:
ping -c 5 8.8.8.8 ping -c 5
如果内网通但外网不通,可能是NAT或路由问题。
第二步,分析连接状态:
ss -tan state syn-recv | wc -l
如果SYN_RECV状态连接很多,可能是SYN Flood攻击。
第三步,检查防火墙:
iptables -L -n iptables -L -n -t nat
第四步,处理措施:
DDoS攻击:使用iptables限速或接入云防护
配置不当:修复防火墙规则或路由
带宽不足:升级带宽或优化应用
六、综合排查案例
6.1 案例一:服务器负载高但CPU使用率不高
现象:uptime显示load average很高,但top显示CPU使用率不高。
分析:load average高但CPU空闲,说明进程在等待IO或其他资源,而不是在计算。
排查步骤:
用vmstat查看:
vmstat 2 5
关注r列(运行队列)和b列(阻塞进程)。
用iostat查看IO:
iostat -x 2 5
看哪个磁盘的%util很高。
用iotop定位进程:
iotop
看哪个进程的IO最多。
根因:很可能是日志写入或数据库IO导致。
6.2 案例二:内存持续增长
现象:free命令显示内存使用持续增长,但应用日志没有明显异常。
分析:可能是内存泄漏或缓存增长。
排查步骤:
查看进程内存占用:
ps aux --sort=-%mem | head -20
监控特定进程:
for i in {1..30}; do ps -o pid,rss,vsz -p ; sleep 10; done
检查swap使用:
free -h vmstat 2 5
根因:可能是应用内存泄漏或JVM heap配置过大。
6.3 案例三:CPU使用率高但找不到高CPU进程
现象:top显示CPU使用率很高,但ps命令找不到占用CPU高的进程。
分析:可能是系统调用或中断导致的CPU消耗。
排查步骤:
查看系统CPU消耗:
top
看sy(系统调用)占比。
查看中断:
cat /proc/interrupts
查看软中断:
cat /proc/softirqs
用strace分析进程:
strace -p-c
根因:可能是大量系统调用、软中断或网络中断。
七、性能优化建议
7.1 系统参数优化
调整文件描述符限制。高并发服务需要调整文件描述符限制:
# 查看当前限制 ulimit -n # 临时调整 ulimit -n 65535 # 永久调整,编辑/etc/security/limits.conf * soft nofile 65535 * hard nofile 65535
调整内核参数。编辑/etc/sysctl.conf:
# 增加tcp连接最大数量 net.ipv4.tcp_max_syn_backlog = 65535 # 调整socket缓冲区大小 net.core.rmem_max = 16777216 net.core.wmem_max = 16777216 # 调整TIME_WAIT复用 net.ipv4.tcp_tw_reuse = 1 # 调整文件描述符 fs.file-max = 65535
使配置生效:
sysctl -p
7.2 应用配置优化
JVM优化。对于Java应用,合理的JVM参数很重要:
-Xms4g -Xmx4g # 堆内存大小 -XX:+UseG1GC # G1垃圾回收器 -XX:MaxGCPauseMillis=200 # 最大GC停顿时间
Nginx优化:
worker_processes auto;
worker_rlimit_nofile 65535;
events {
worker_connections 65535;
use epoll;
}
7.3 监控和告警
建立完善的监控体系是预防性能问题的关键。
关键告警指标:
系统负载 > CPU核心数 * 0.8
内存使用率 > 85%
磁盘使用率 > 80%
CPU iowait > 20%
网络连接数异常增长
建议使用Prometheus + Grafana或云监控服务。
总结
Linux性能排查的核心是建立系统化的思路:
先整体后局部:先用vmstat、iostat等工具确认问题类型,再定位具体进程
先CPU后内存、IO:CPU是最容易排查的,从它开始
多个指标配合看:单一指标可能误导,配合多个指标分析
找到根因再处理:不要盲目杀进程或重启服务,找到根因才能根本解决
常用命令速查:
# 系统整体状态
uptime
vmstat 2 5
# CPU分析
top
ps aux --sort=-%cpu | head -10
# 内存分析
free -h
ps aux --sort=-%mem | head -10
# IO分析
iostat -x 2 5
iotop
# 网络分析
ss -s
netstat -an | awk '/^tcp/{print $NF}' | sort | uniq -c
# 进程详细分析
strace -p -c
lsof -p
pmap -x
性能优化是一个持续的过程,需要在日常运维中不断积累经验,建立完善的监控体系,才能在问题发生前发现问题。
八、生产环境实战案例
8.1 案例:Java应用频繁Full GC导致服务卡顿
背景:某电商平台促销活动期间,订单接口响应时间从正常200ms飙升至5-10秒,用户投诉页面加载缓慢。
排查过程:
初步诊断。登录服务器,用top查看CPU使用率,发现并不高,但load average偏高:
uptime # 1612 up 45 days, 3:22, load average: 12.85, 10.21, 8.10 top # 发现多个Java进程CPU使用率不高但运行时间很长
分析GC情况。用jstat查看GC统计:
jstat -gc 12345 1000 10 # 每秒打印一次Java进程12345的GC统计
输出显示:FGC(Full GC)次数很多,每次Full GC耗时超过2秒。这是典型的GC过于频繁导致的服务卡顿。
分析堆内存。用jmap查看堆内存使用:
jmap -heap 12345
输出显示:Heap配置了8GB,但老年代使用率持续在95%以上,说明内存分配不合理或者存在内存泄漏。
查看GC日志:
cat /var/log/myapp/gc.log | tail -100
GC日志显示:对象创建速度远大于回收速度,导致频繁Full GC。
根因:JVM heap配置过大(8GB),导致GC时扫描的内存区域过大,单次GC停顿时间过长。同时应用存在对象创建过多的问题。
修复方案:
降低JVM heap大小,从8GB降到4GB
启用G1垃圾回收器,优化GC参数
优化应用代码,减少不必要的对象创建
修复后的JVM参数:
-Xms4g -Xmx4g -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -XX:G1HeapRegionSize=4m -XX:InitiatingHeapOccupancyPercent=45 -XX:G1ReservePercent=15
验证修复:
# 观察GC情况
jstat -gc 12345 1000 10
# 检查接口响应时间
curl -o /dev/null -s -w "%{time_total}
" http://localhost:8080/api/orders
总结:Java应用性能问题,GC是常见的根因。关键是要监控GC情况,分析GC日志,合理配置JVM参数。
8.2 案例:Nginx连接数暴涨导致服务不可用
背景:某网站突然无法访问,Nginx返回502 Bad Gateway错误。
排查过程:
检查Nginx状态:
systemctl status nginx # 显示nginx is running netstat -an | grep :80 | wc -l # 连接数超过60000
分析连接状态:
netstat -an | awk '/^tcp/{print $6}' | sort | uniq -c | sort -rn
输出显示大量TIME_WAIT状态连接,说明上游服务处理能力不足。
检查上游PHP-FPM:
systemctl status php-fpm # 显示php-fpm正常运行 netstat -an | grep 9000 | wc -l # 9000端口(PHP-FPM)连接数超过10000
检查PHP-FPM进程数:
ps aux | grep php-fpm | wc -l # 只有50个worker进程 cat /etc/php-fpm.d/www.conf | grep ^pm.max_children # pm.max_children = 50
根因:PHP-FPM的max_children设置为50,但连接数远超这个数字,导致请求排队或被拒绝。
修复方案:
临时增加PHP-FPM进程数:
# 编辑 /etc/php-fpm.d/www.conf pm.max_children = 200 pm.start_servers = 50 pm.min_spare_servers = 50 pm.max_spare_servers = 200 pm.max_requests = 500 # 重启PHP-FPM systemctl restart php-fpm
调整Nginx超时配置:
proxy_connect_timeout 60s; proxy_send_timeout 60s; proxy_read_timeout 60s;
启用TCP连接复用:
upstream backend {
server 127.0.0.1:9000;
keepalive 200;
}
优化数据库连接。检查数据库连接是否成为瓶颈,如果是,需要增加连接池大小或优化查询。
总结:高并发场景下,PHP-FPM等上游服务的进程数配置很重要。要结合服务器资源和业务特点合理配置。
8.3 案例:MySQL慢查询导致网站响应缓慢
背景:某论坛网站访问速度变慢,首页加载需要10秒以上。
排查过程:
检查Web服务器:
top # CPU和内存使用正常 netstat -an | grep :80 | wc -l # 连接数正常
检查MySQL:
mysql -u root -p -e "SHOW PROCESSLISTG" | head -50
输出显示多个查询运行时间超过30秒,最长的超过5分钟。
查看慢查询日志:
cat /var/log/mysql/slow-query.log | tail -50
发现多个未建索引的JOIN查询,单表数据量超过千万级别。
分析查询计划:
mysql -u root -p -e "EXPLAIN SELECT * FROM posts JOIN users ON posts.user_id = users.id WHERE posts.created_at > '2026-01-01'G"
输出显示:全表扫描,没有使用索引。
根因:posts表缺少user_id和created_at的联合索引,查询时全表扫描。
修复方案:
添加索引(高风险操作,需要谨慎):
-- 先备份 mysqldump -u root -p mydb posts > /backup/posts.sql -- 添加索引(注意:在大表上添加索引可能很慢,需要在业务低峰期执行) ALTER TABLE posts ADD INDEX idx_user_created (user_id, created_at);
优化查询语句:
-- 避免SELECT * SELECT id, title, created_at FROM posts WHERE user_id = 123;
配置慢查询日志自动分析:
# /etc/mysql/my.cnf slow_query_log = 1 slow_query_log_file = /var/log/mysql/slow-query.log long_query_time = 2
验证修复:
mysql -u root -p -e "EXPLAIN SELECT * FROM posts WHERE user_id = 123 AND created_at > '2026-01-01'G" # 确认使用了索引
总结:数据库查询性能问题,首先要开启慢查询日志,定位慢查询,然后分析执行计划,添加合适的索引。
8.4 案例:服务器遭遇DDoS攻击
背景:服务器网络带宽突然占满,服务器无法远程访问,网站完全无法访问。
排查过程:
检查带宽:
cat /proc/net/dev | grep eth0 # 发现接收字节数异常高
分析连接:
netstat -an | awk '/^tcp/{print $5}' | cut -d: -f1 | sort | uniq -c | sort -rn | head -20
发现大量来自同一IP段的连接。
查看连接状态:
ss -tan state syn-recv | wc -l # 超过50000个SYN_RECV连接
根因:SYN Flood攻击,攻击者发送大量SYN包但不完成三次握手,耗尽服务器连接资源。
处理措施:
使用iptables临时屏蔽攻击IP:
# 屏蔽单个IP iptables -I INPUT -s 1.2.3.4 -j DROP # 屏蔽IP段 iptables -I INPUT -s 1.2.3.0/24 -j DROP
优化内核参数缓解SYN Flood:
# 编辑 /etc/sysctl.conf net.ipv4.tcp_syncookies = 1 net.ipv4.tcp_max_syn_backlog = 65535 net.ipv4.tcp_syn_retries = 2 net.ipv4.tcp_synack_retries = 2 # 使配置生效 sysctl -p
使用fail2ban自动屏蔽:
yum install fail2ban -y # 配置fail2ban cat > /etc/fail2ban/jail.local << 'EOF' [DEFAULT] bantime = 3600 findtime = 600 maxretry = 100 [ssh-iptables] enabled = true filter = sshd action = iptables[name=SSH, port=ssh, protocol=tcp] logpath = /var/log/secure maxretry = 5 [nginx-http-auth] enabled = true filter = nginx-http-auth action = iptables[name=nginx-auth, port=http, protocol=tcp] logpath = /var/log/nginx/error.log maxretry = 10 EOF systemctl enable fail2ban systemctl start fail2ban
接入云防护服务。如果是大规模DDoS攻击,本地防护很难应对,建议接入云服务商提供的DDoS防护服务。
总结:DDoS攻击是常见的网络安全问题,需要建立多层防护机制。应用层可以用iptables和fail2ban,基础设施层建议使用云防护服务。
九、常用调优参数汇总
9.1 系统内核参数
编辑/etc/sysctl.conf,添加以下参数:
# 网络参数 net.ipv4.tcp_syncookies = 1 net.ipv4.tcp_tw_reuse = 1 net.ipv4.tcp_fin_timeout = 30 net.ipv4.tcp_keepalive_time = 1200 net.ipv4.ip_local_port_range = 1024 65535 net.ipv4.tcp_max_syn_backlog = 65535 net.ipv4.tcp_max_tw_buckets = 5000 net.core.somaxconn = 65535 net.core.rmem_max = 16777216 net.core.wmem_max = 16777216 net.ipv4.tcp_rmem = 4096 87380 16777216 net.ipv4.tcp_wmem = 4096 65536 16777216 # 文件系统参数 fs.file-max = 65535 fs.inotify.max_user_watches = 524288 # 内存参数 vm.swappiness = 10 vm.dirty_ratio = 60 vm.dirty_background_ratio = 5
使配置生效:
sysctl -p
9.2 limits.conf参数
编辑/etc/security/limits.conf:
* soft nofile 65535 * hard nofile 65535 * soft nproc 65535 * hard nproc 65535
9.3 常用监控命令脚本
编写一个简单的性能监控脚本:
#!/bin/bash # performance_monitor.sh LOG_FILE="/var/log/performance_$(date +%Y%m%d).log" echo"=== $(date) ===" >> $LOG_FILE echo"=== System Load ===" >> $LOG_FILE uptime >> $LOG_FILE echo"=== Memory Usage ===" >> $LOG_FILE free -h >> $LOG_FILE echo"=== Top 10 CPU Processes ===" >> $LOG_FILE ps aux --sort=-%cpu | head -11 >> $LOG_FILE echo"=== Top 10 Memory Processes ===" >> $LOG_FILE ps aux --sort=-%mem | head -11 >> $LOG_FILE echo"=== Disk IO ===" >> $LOG_FILE iostat -x 1 1 >> $LOG_FILE echo"=== Network Connections ===" >> $LOG_FILE ss -s >> $LOG_FILE echo"=== Done ===" >> $LOG_FILE
加入crontab定期执行:
crontab -e # 每天早上9点执行 0 9 * * * /bin/bash /opt/scripts/performance_monitor.sh
十、总结
Linux性能排查需要建立系统化的思维框架:
理解四大资源:CPU、内存、磁盘IO、网络是性能问题的四个主要方向
掌握核心工具:top、vmstat、iostat、ss、netstat是排查的瑞士军刀
建立排查顺序:先整体后局部,先CPU后内存,IO网络配合看
多指标综合分析:单一指标可能误导,要配合多个指标判断
找到根因再处理:不要盲目重启服务,找到根本原因才能彻底解决
性能优化是一个持续的过程,需要在实践中不断积累经验。推荐的做法:
建立完善的监控体系,在问题发生前发现异常
定期巡检,记录性能基线,便于对比分析
重大变更前做性能测试,避免上线后才发现问题
保留性能问题排查记录,形成知识沉淀
性能问题的排查和优化没有捷径,只有多实践、多总结,才能在遇到问题时快速定位、妥善处理。
全部0条评论
快来发表一下你的评论吧 !