跳转到内容

性能调优

性能调优是一个系统化的过程:先定位瓶颈,再有针对性地优化。盲目调参往往适得其反。本文介绍常见的调优手段和适用场景,帮助你从内核参数到应用层逐步提升服务器性能。

在调优之前,必须先记录当前的性能基线,否则无法衡量优化效果。

Terminal window
# 记录系统基本信息
uname -a
cat /etc/os-release
lscpu
free -h
lsblk
# 安装性能分析工具
sudo dnf install sysstat perf iotop htop -y
# 启用 sysstat 数据收集
sudo systemctl enable --now sysstat
# 查看历史性能数据
sar -u 1 5 # CPU 使用率
sar -r 1 5 # 内存使用率
sar -d 1 5 # 磁盘 I/O
sar -n DEV 1 5 # 网络吞吐
Terminal window
# 快速判断瓶颈类型
# CPU 瓶颈:load average 持续高于 CPU 核心数
uptime
# 内存瓶颈:可用内存低且 swap 活跃
free -h
vmstat 1 5
# I/O 瓶颈:iowait 高
iostat -xz 1 5
# 网络瓶颈:丢包或带宽饱和
ss -s
sar -n DEV 1 5

sysctl 用于在运行时修改内核参数。

Terminal window
# 查看所有参数
sysctl -a
# 查看特定参数
sysctl net.core.somaxconn
sysctl vm.swappiness
# 临时修改(重启后失效)
sudo sysctl -w net.core.somaxconn=65535
# 永久修改
sudo tee /etc/sysctl.d/99-tuning.conf > /dev/null <<'EOF'
# 自定义内核参数调优
EOF
# 应用配置
sudo sysctl --system
Terminal window
sudo tee /etc/sysctl.d/99-network.conf > /dev/null <<'EOF'
# ==============================
# 网络性能调优
# ==============================
# --- TCP 缓冲区 ---
# 默认和最大的 TCP 发送/接收缓冲区(字节)
# 格式:min default max
net.core.rmem_default = 262144
net.core.rmem_max = 16777216
net.core.wmem_default = 262144
net.core.wmem_max = 16777216
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216
# --- 连接队列 ---
# 监听队列最大长度(影响高并发下的连接建立)
net.core.somaxconn = 65535
# 半连接队列大小
net.ipv4.tcp_max_syn_backlog = 65535
# 网卡接收队列长度
net.core.netdev_max_backlog = 65535
# --- TCP 连接优化 ---
# 启用 TCP Fast Open(减少握手延迟)
net.ipv4.tcp_fastopen = 3
# TIME_WAIT 相关
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 15
net.ipv4.tcp_max_tw_buckets = 262144
# Keepalive 参数
net.ipv4.tcp_keepalive_time = 600
net.ipv4.tcp_keepalive_intvl = 30
net.ipv4.tcp_keepalive_probes = 5
# --- 拥塞控制 ---
# 使用 BBR 拥塞控制算法(推荐)
net.core.default_qdisc = fq
net.ipv4.tcp_congestion_control = bbr
# --- 本地端口范围 ---
net.ipv4.ip_local_port_range = 1024 65535
# --- 其他 ---
# 允许更多的 orphan 套接字
net.ipv4.tcp_max_orphans = 262144
# SYN Flood 防护
net.ipv4.tcp_syncookies = 1
EOF
sudo sysctl --system

验证 BBR 是否生效:

Terminal window
sysctl net.ipv4.tcp_congestion_control
# 输出应为:net.ipv4.tcp_congestion_control = bbr
lsmod | grep bbr
Terminal window
sudo tee /etc/sysctl.d/99-memory.conf > /dev/null <<'EOF'
# ==============================
# 内存调优
# ==============================
# Swappiness:控制内核将内存页交换到 swap 的倾向
# 0 = 尽量不使用 swap(适合内存充足的数据库服务器)
# 10 = 低交换倾向(推荐大多数服务器场景)
# 60 = 默认值
vm.swappiness = 10
# 脏页刷新策略
# 脏页超过内存百分比时后台开始刷新
vm.dirty_background_ratio = 5
# 脏页超过此比例时前台进程必须等待刷新
vm.dirty_ratio = 15
# 脏页存活时间(厘秒,500 = 5秒)
vm.dirty_expire_centisecs = 500
# 刷新线程唤醒间隔(厘秒)
vm.dirty_writeback_centisecs = 100
# VFS 缓存压力(默认 100)
# 低于 100 = 倾向保留 dentry/inode 缓存
# 高于 100 = 倾向回收缓存
vm.vfs_cache_pressure = 50
# 内存不足时的行为
# 0 = 启发式 OOM(默认)
# 1 = 允许过量分配
# 2 = 不允许过量分配
vm.overcommit_memory = 0
EOF
sudo sysctl --system

大页可以减少 TLB 缺失,提升内存密集型应用(如数据库)的性能。

Terminal window
# 查看当前大页配置
grep -i huge /proc/meminfo
# 计算需要的大页数量
# 例如为数据库分配 4GB:4096MB / 2MB(默认大页大小)= 2048 页
echo "需要的大页数: $((4096 / 2))"
# 设置大页数量
sudo sysctl -w vm.nr_hugepages=2048
# 永久配置
echo 'vm.nr_hugepages = 2048' | sudo tee -a /etc/sysctl.d/99-memory.conf
sudo sysctl --system
# 验证
grep -i huge /proc/meminfo
# HugePages_Total: 2048
# HugePages_Free: 2048
# Hugepagesize: 2048 kB

THP 由内核自动管理大页分配。对于大多数服务器应用是有益的,但某些数据库(如 MongoDB、Redis)建议禁用 THP 以避免延迟抖动。

Terminal window
# 查看当前状态
cat /sys/kernel/mm/transparent_hugepage/enabled
# 临时禁用
echo never | sudo tee /sys/kernel/mm/transparent_hugepage/enabled
echo never | sudo tee /sys/kernel/mm/transparent_hugepage/defrag
# 永久禁用(通过 systemd)
sudo tee /etc/systemd/system/disable-thp.service > /dev/null <<'EOF'
[Unit]
Description=Disable Transparent Huge Pages
DefaultDependencies=no
After=sysinit.target local-fs.target
Before=basic.target
[Service]
Type=oneshot
ExecStart=/bin/sh -c 'echo never > /sys/kernel/mm/transparent_hugepage/enabled'
ExecStart=/bin/sh -c 'echo never > /sys/kernel/mm/transparent_hugepage/defrag'
[Install]
WantedBy=basic.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable disable-thp

ulimit 控制用户进程可使用的系统资源上限。默认值通常偏保守,高并发场景需要调整。

Terminal window
# 查看当前用户的所有限制
ulimit -a
# 关键参数:
# -n 最大打开文件数(open files)
# -u 最大进程数(max user processes)
# -l 最大锁定内存(max locked memory)
Terminal window
# 修改系统级限制
sudo tee /etc/security/limits.d/99-tuning.conf > /dev/null <<'EOF'
# 格式:<domain> <type> <item> <value>
# 所有用户
* soft nofile 65535
* hard nofile 131072
* soft nproc 65535
* hard nproc 131072
# 特定用户(如 nginx)
nginx soft nofile 131072
nginx hard nofile 262144
# root 用户
root soft nofile 131072
root hard nofile 262144
EOF

对于 systemd 管理的服务,还需要在 service 文件中设置:

Terminal window
# 方法一:修改 systemd 默认限制
sudo mkdir -p /etc/systemd/system.conf.d
sudo tee /etc/systemd/system.conf.d/limits.conf > /dev/null <<'EOF'
[Manager]
DefaultLimitNOFILE=131072
DefaultLimitNPROC=65535
EOF
# 方法二:为特定服务设置(推荐)
sudo systemctl edit nginx
# 在编辑器中添加:
# [Service]
# LimitNOFILE=131072
# LimitNPROC=65535
sudo systemctl daemon-reload
sudo systemctl restart nginx
# 验证服务的实际限制
cat /proc/$(pidof nginx | awk '{print $1}')/limits

tuned 是 EL 系发行版提供的动态调优守护进程,内置多种预定义的调优方案。

Terminal window
sudo dnf install tuned -y
sudo systemctl enable --now tuned
# 查看所有可用的调优方案
tuned-adm list
# 常用方案:
# throughput-performance - 高吞吐量优化
# latency-performance - 低延迟优化
# network-latency - 网络低延迟
# network-throughput - 网络高吞吐
# virtual-guest - 虚拟机客户机
# virtual-host - 虚拟化宿主机
# postgresql - PostgreSQL 优化
# 查看当前方案
tuned-adm active
# 切换方案
sudo tuned-adm profile throughput-performance
# 获取推荐方案
tuned-adm recommend
# 查看方案的具体配置
tuned-adm profile_info throughput-performance
Terminal window
# 基于现有方案创建自定义方案
sudo mkdir -p /etc/tuned/my-web-server
sudo tee /etc/tuned/my-web-server/tuned.conf > /dev/null <<'EOF'
[main]
summary=Custom tuning for web server
include=throughput-performance
[sysctl]
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 65535
net.ipv4.tcp_tw_reuse = 1
net.core.default_qdisc = fq
net.ipv4.tcp_congestion_control = bbr
vm.swappiness = 10
[vm]
transparent_hugepages = never
[disk]
readahead = 4096
EOF
# 应用自定义方案
sudo tuned-adm profile my-web-server
sudo tuned-adm active

I/O 调度器决定了磁盘读写请求的排序和合并策略。

Terminal window
# 查看当前 I/O 调度器
cat /sys/block/sda/queue/scheduler
# 输出示例:[mq-deadline] kyber bfq none
# 临时修改
echo "kyber" | sudo tee /sys/block/sda/queue/scheduler
# 永久修改(通过 udev 规则)
sudo tee /etc/udev/rules.d/60-io-scheduler.rules > /dev/null <<'EOF'
# SSD 使用 none (noop) 或 mq-deadline
ACTION=="add|change", KERNEL=="sd[a-z]", ATTR{queue/rotational}=="0", ATTR{queue/scheduler}="none"
# HDD 使用 bfq
ACTION=="add|change", KERNEL=="sd[a-z]", ATTR{queue/rotational}=="1", ATTR{queue/scheduler}="bfq"
EOF
调度器适用场景
none(noop)NVMe SSD、虚拟机(宿主机已做调度)
mq-deadline通用 SSD,数据库场景(保证截止时间)
bfqHDD,桌面/交互场景(公平调度)
kyber高速 SSD,高吞吐场景
Terminal window
# 查看当前预读值(单位:512字节扇区)
cat /sys/block/sda/queue/read_ahead_kb
# 顺序读密集的场景可增大预读
echo 2048 | sudo tee /sys/block/sda/queue/read_ahead_kb
# 随机读密集的场景(如数据库)减小预读
echo 128 | sudo tee /sys/block/sda/queue/read_ahead_kb

将网卡中断绑定到特定 CPU 核心,减少上下文切换:

Terminal window
# 查看网卡中断分布
cat /proc/interrupts | grep eth0
# 自动设置(使用 irqbalance 服务)
sudo systemctl enable --now irqbalance
# 或手动绑定(多队列网卡场景)
# 查看网卡队列
ls /sys/class/net/eth0/queues/
# 安装 tuned 的 network 插件可自动优化
Terminal window
# 安装 ethtool
sudo dnf install ethtool -y
# 查看网卡信息
ethtool eth0
# 查看和修改环形缓冲区大小
ethtool -g eth0 # 查看
sudo ethtool -G eth0 rx 4096 tx 4096 # 修改
# 查看和启用网卡特性
ethtool -k eth0 # 查看
sudo ethtool -K eth0 tso on # 启用 TCP 分段卸载
sudo ethtool -K eth0 gro on # 启用通用接收卸载
sudo ethtool -K eth0 gso on # 启用通用分段卸载

高并发代理/NAT 服务器需要增大连接跟踪表:

Terminal window
sudo tee /etc/sysctl.d/99-conntrack.conf > /dev/null <<'EOF'
# 连接跟踪表最大条目数
net.netfilter.nf_conntrack_max = 1048576
# 连接跟踪表的哈希桶大小
# 通常设为 nf_conntrack_max 的 1/4
net.netfilter.nf_conntrack_buckets = 262144
# 缩短各状态的超时时间
net.netfilter.nf_conntrack_tcp_timeout_established = 3600
net.netfilter.nf_conntrack_tcp_timeout_time_wait = 30
net.netfilter.nf_conntrack_tcp_timeout_close_wait = 15
net.netfilter.nf_conntrack_tcp_timeout_fin_wait = 30
EOF
sudo sysctl --system
Terminal window
# 查看 XFS 挂载选项
mount | grep xfs
# 优化挂载选项(编辑 /etc/fstab)
# noatime - 不更新访问时间,减少写入
# nodiratime - 不更新目录访问时间
# logbufs=8 - 增加日志缓冲区
# 示例:
# /dev/sda1 /data xfs defaults,noatime,nodiratime,logbufs=8 0 0
# 重新挂载生效(不需要重启)
sudo mount -o remount,noatime,nodiratime /data
Terminal window
# 优化挂载选项
# noatime - 不更新访问时间
# commit=60 - 数据提交间隔(秒),增大可提高性能但增加数据丢失风险
# 示例:
# /dev/sdb1 /data ext4 defaults,noatime,commit=60 0 2
sudo mount -o remount,noatime /data
/usr/local/bin/perf_check.sh
#!/bin/bash
# 检查当前系统性能参数配置
echo "============================================"
echo " 性能参数检查报告 - $(date)"
echo "============================================"
echo ""
echo "--- CPU ---"
echo "核心数: $(nproc)"
echo "当前负载: $(uptime | awk -F'load average:' '{print $2}')"
echo "调度器: $(tuned-adm active 2>/dev/null || echo '未安装 tuned')"
echo ""
echo "--- 内存 ---"
free -h
echo "swappiness: $(sysctl -n vm.swappiness)"
echo "dirty_ratio: $(sysctl -n vm.dirty_ratio)"
echo "dirty_background_ratio: $(sysctl -n vm.dirty_background_ratio)"
echo "THP: $(cat /sys/kernel/mm/transparent_hugepage/enabled)"
echo "HugePages: $(grep HugePages_Total /proc/meminfo)"
echo ""
echo "--- 网络 ---"
echo "somaxconn: $(sysctl -n net.core.somaxconn)"
echo "tcp_max_syn_backlog: $(sysctl -n net.ipv4.tcp_max_syn_backlog)"
echo "tcp_congestion: $(sysctl -n net.ipv4.tcp_congestion_control)"
echo "ip_local_port_range: $(sysctl -n net.ipv4.ip_local_port_range)"
echo "tcp_tw_reuse: $(sysctl -n net.ipv4.tcp_tw_reuse)"
echo ""
echo "--- 文件描述符 ---"
echo "系统级限制: $(sysctl -n fs.file-max)"
echo "当前使用量: $(cat /proc/sys/fs/file-nr)"
echo "ulimit -n (当前用户): $(ulimit -n)"
echo ""
echo "--- I/O ---"
for disk in $(lsblk -dn -o NAME); do
scheduler=$(cat /sys/block/$disk/queue/scheduler 2>/dev/null)
readahead=$(cat /sys/block/$disk/queue/read_ahead_kb 2>/dev/null)
rotational=$(cat /sys/block/$disk/queue/rotational 2>/dev/null)
type="HDD"
[ "$rotational" = "0" ] && type="SSD"
echo "${disk} (${type}): 调度器=${scheduler}, 预读=${readahead}KB"
done
echo ""
echo "--- 连接跟踪 ---"
if [ -f /proc/sys/net/netfilter/nf_conntrack_max ]; then
echo "最大连接数: $(sysctl -n net.netfilter.nf_conntrack_max)"
echo "当前连接数: $(cat /proc/sys/net/netfilter/nf_conntrack_count 2>/dev/null || echo N/A)"
else
echo "nf_conntrack 模块未加载"
fi
Terminal window
chmod +x /usr/local/bin/perf_check.sh
  1. 先测量后优化 — 使用 sarvmstatiostatperf 定位真正的瓶颈
  2. 每次只改一个参数 — 这样才能确认是哪个改动带来了效果
  3. 记录每次变更 — 方便回退和复盘
  4. 压力测试验证 — 使用 abwrkfiosysbench 等工具验证优化效果
  5. 关注副作用 — 某些参数的优化可能在其他维度引入问题
Terminal window
# 常用压测工具
sudo dnf install httpd-tools -y # 提供 ab
# ab -n 10000 -c 100 http://localhost/
# fio 磁盘性能测试
sudo dnf install fio -y
fio --name=randread --ioengine=libaio --rw=randread --bs=4k \
--size=1G --numjobs=4 --runtime=60 --group_reporting
# sysbench CPU 测试
sudo dnf install sysbench -y
sysbench cpu --threads=$(nproc) run