内核参数调优:sysctl 里值得改的十来个值

默认内核参数面向「通用场景」,对 Web 服务器来说偏保守。改几个值能明显提升并发能力——但也可能改出问题,所以要理解每个值在干什么。

一、先看当前值

bash
sysctl -a                        # 全部(很多)
sysctl net.ipv4.tcp_syncookies
sysctl -a | grep -i "somaxconn"

# 临时修改(重启失效)
sudo sysctl -w net.core.somaxconn=65535

# 永久生效:写进 /etc/sysctl.d/
echo "net.core.somaxconn=65535" | sudo tee -a /etc/sysctl.d/99-baize.conf
sudo sysctl --system             # 重新加载所有配置

优先写 /etc/sysctl.d/99-xxx.conf,不要直接改 /etc/sysctl.conf,分文件更好管理。

二、网络相关(Web 服务器重点)

nginx
# /etc/sysctl.d/99-baize.conf

# 1. 监听队列长度:高并发时默认 128 太小
net.core.somaxconn = 65535

# 2. 半连接队列:防 SYN flood,同时要够用
net.ipv4.tcp_max_syn_backlog = 65535

# 3. SYN cookies:防 SYN flood,一般建议开
net.ipv4.tcp_syncookies = 1

# 4. TIME_WAIT 复用:短连接多时必开
net.ipv4.tcp_tw_reuse = 1

# 5. TIME_WAIT 最大数量
net.ipv4.tcp_max_tw_buckets = 262144

# 6. 本地端口范围:作为客户端时可用端口(反代到后端会用)
net.ipv4.ip_local_port_range = 1024 65535

# 7. 启用窗口缩放,高延迟网络下提升吞吐
net.ipv4.tcp_window_scaling = 1

# 8. 自动调优接收/发送缓冲区
net.ipv4.tcp_moderate_rcvbuf = 1
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216

# 9. 拥塞控制算法:BBR 对长肥管道(高延迟高带宽)效果明显
net.ipv4.tcp_congestion_control = bbr
net.core.default_qdisc = fq

# 10. 开启转发(做网关/NAT 时才需要,普通 Web 服务器不用)
# net.ipv4.ip_forward = 1
bash
sudo sysctl --system

# 确认 BBR 生效
sysctl net.ipv4.tcp_congestion_control
lsmod | grep bbr

关于 tcp_tw_recycle

这个值已经被内核移除,也不要再设。 它在 NAT 环境下会导致连接被随机丢弃,是个历史坑。网上老教程还在推荐,别信。

三、文件描述符

「too many open files」是高并发下的经典错误。

bash
ulimit -n                    # 当前会话限制,默认常是 1024
ulimit -Hn                   # 硬限制
cat /proc/sys/fs/file-max    # 系统全局上限
cat /proc/sys/fs/file-nr     # 已用/空闲/上限
nginx
# 系统级
fs.file-max = 1000000
fs.nr_open = 1000000

用户级在 /etc/security/limits.conf

bash
# /etc/security/limits.conf
*       soft    nofile    65535
*       hard    nofile    65535
root    soft    nofile    65535
root    hard    nofile    65535

systemd 服务的限制要在 unit 文件里单独设(limits.conf 对 systemd 服务不生效):

nginx
[Service]
LimitNOFILE=65535
bash
# 看某个进程的实际限制
cat /proc/<PID>/limits | grep "open files"

四、内存与交换

nginx
# swappiness:值越小越倾向用物理内存
# 服务器(尤其是数据库)建议 1~10
vm.swappiness = 10

# 脏页写回阈值(占内存比例),写密集场景可调小让回写更平滑
vm.dirty_ratio = 20
vm.dirty_background_ratio = 10

# 内存分配策略:Redis 等建议设 1(避免 overcommit 导致 fork 失败)
vm.overcommit_memory = 1

# 禁用 IPv6(仅在确认不用时)
# net.ipv6.conf.all.disable_ipv6 = 1

五、安全相关

nginx
# 忽略 ICMP 广播,防 smurf 攻击
net.ipv4.icmp_echo_ignore_broadcasts = 1

# 不响应 ICMP 重定向(防路由劫持)
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.all.send_redirects = 0

# 开启反向路径过滤,防 IP 欺骗
net.ipv4.conf.all.rp_filter = 1

# 记录可疑包( martian packet,源地址不可能的包)
net.ipv4.conf.all.log_martians = 1

六、验证效果

bash
# 连接状态分布(看 TIME_WAIT 多不多)
ss -ant | awk '{print $1}' | sort | uniq -c | sort -rn

# 看监听队列有没有溢出
netstat -s | grep -i "listen"
# 或
ss -lnt
# Recv-Q / Send-Q 长期不为 0 说明有积压

# 压测(别对生产环境乱压)
# wrk -t4 -c100 -d30s http://127.0.0.1/

七、风险提示

在改之前,请记住:

  1. 一次只改一个值,改完观察,别一次套用网上一整份「优化脚本」;
  2. 改完用 sysctl --system 生效,重启验证一次;
  3. 留好回滚方式:配置文件分文件放,出问题注释掉即可;
  4. 大部分参数只有高并发下才有区别。日访问几千的站点,默认值完全够用;
  5. 云厂商的镜像往往已做过基础优化,先看看再改。
bash
# 备份当前配置,方便对比
sudo sysctl -a > /tmp/sysctl-before.conf

八、一份保守的通用配置

nginx
# /etc/sysctl.d/99-baize.conf
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 65535
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.ip_local_port_range = 1024 65535
net.ipv4.tcp_congestion_control = bbr
net.core.default_qdisc = fq
fs.file-max = 200000
vm.swappiness = 10
net.ipv4.icmp_echo_ignore_broadcasts = 1
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.all.rp_filter = 1

这份配置在各类 Web 服务器上都算安全,没有激进值。


调优的原则是按需。没有压测数据支撑的优化,本质上是在碰运气。