Linux服务器性能排查完整流程

描述

引言

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 -gc  1000 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 -gc 
jmap -heap 

 

原因二:缓存数据过大。Nginx、Redis等应用会使用大量内存作为缓存。

排查方法:检查应用配置,确认缓存大小限制。

原因三:JVM heap配置过大。如果JVM的heap配置超过了物理内存的一半,可能影响系统稳定性。

排查方法:检查JVM参数:

 

jcmd  VM.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网络配合看

多指标综合分析:单一指标可能误导,要配合多个指标判断

找到根因再处理:不要盲目重启服务,找到根本原因才能彻底解决

性能优化是一个持续的过程,需要在实践中不断积累经验。推荐的做法:

建立完善的监控体系,在问题发生前发现异常

定期巡检,记录性能基线,便于对比分析

重大变更前做性能测试,避免上线后才发现问题

保留性能问题排查记录,形成知识沉淀

性能问题的排查和优化没有捷径,只有多实践、多总结,才能在遇到问题时快速定位、妥善处理。

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分