Linux 的 sysctl 接口暴露了数百个内核参数,但绝大多数参数在默认值下已经足够优秀。盲目地“抄作业”式调优不仅不会提升性能,反而可能引入稳定性问题。本文聚焦于那些在高并发、大流量场景下真正能产生可观测差异的参数,并解释其背后的原理,帮助你做出有依据的调优决策。
一、调优前必须明确的三件事
在修改任何参数之前,请先确认以下前提:
- 默认值是经过验证的:内核社区维护默认值的基准是通用场景下的稳定性,而非极致性能。
- 调优是场景驱动的:Web 服务器、数据库、负载均衡器的瓶颈点完全不同,没有万能配置。
- 可观测性优先:没有监控数据支撑的调优都是猜测。先用
sar、ss、netstat、iostat定位瓶颈,再动参数。
二、网络栈:高并发场景的核心战场
网络参数是 sysctl 调优中出现频率最高、效果也最明显的一类。
2.1 连接队列:应对突发流量
net.core.somaxconn = 32768
net.ipv4.tcp_max_syn_backlog = 8192
somaxconn 限制了 listen() 系统调用的 backlog 上限。默认值通常为 128 或 4096,在 Nginx、Redis 等接受大量短连接的场景下,这个值很容易被打满,导致新连接被丢弃或客户端超时。将其提升到 32768 是常见做法,但注意应用层也需要同步调整(如 Nginx 的 backlog 指令)。
tcp_max_syn_backlog 控制 SYN 队列长度,在遭受 SYN Flood 或流量突增时尤为关键。对于 16GB 以上内存的服务器,8192 是一个安全的起点。
2.2 TIME_WAIT 与端口耗尽
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 30
net.ipv4.ip_local_port_range = 1024 65535
tcp_tw_reuse 允许将 TIME_WAIT 状态的 socket 重新用于出站连接,这是客户端角色(如反向代理、爬虫)缓解端口耗尽的安全手段。注意:tcp_tw_recycle 已在 Linux 4.12 中被移除,且它在 NAT 环境下会导致连接失败,绝对不要使用。
ip_local_port_range 扩大了可用临时端口范围。默认的 32768 60999 仅有约 28k 个端口,对于每秒数千次出站连接的代理服务器来说,配合 TIME_WAIT 会迅速耗尽。扩展到 1024 65535 可提供约 64k 个端口。
2.3 缓冲区与拥塞控制
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216
net.ipv4.tcp_congestion_control = bbr
net.core.default_qdisc = fq
缓冲区参数在高带宽延迟积(BDP)网络中至关重要。例如,一条 1Gbps、RTT 100ms 的链路,BDP 约为 12.5MB,默认的 6MB 接收缓冲区会成为吞吐量瓶颈。将最大值提升到 16MB 可以充分利用带宽。
拥塞控制算法方面,Google 的 BBR 在丢包率较高的跨国链路上通常显著优于 CUBIC。启用 BBR 需要内核 4.9+,并配合 fq 队列规则:
# 验证
sysctl net.ipv4.tcp_available_congestion_control
2.4 文件描述符与连接跟踪
fs.file-max = 1000000
net.netfilter.nf_conntrack_max = 1048576
net.netfilter.nf_conntrack_tcp_timeout_established = 86400
fs.file-max 是系统级文件描述符上限。现代服务器上,每个 TCP 连接、每个打开的文件都消耗一个 fd。百万级是合理的上限,但真正生效还需要调整 ulimit -n 和 systemd 的 LimitNOFILE。
如果你使用了 iptables 或 Docker,nf_conntrack_max 会成为隐性瓶颈。连接跟踪表满时,内核会打印 nf_conntrack: table full, dropping packet,表现为随机丢包。将其设为内存允许的较大值,并延长已建立连接的超时时间以减少表项周转。
三、内存与虚拟内存:避免 OOM 与交换抖动
vm.swappiness = 10
vm.dirty_ratio = 15
vm.dirty_background_ratio = 5
vm.overcommit_memory = 0
vm.min_free_kbytes = 65536
vm.swappiness 控制内核换出匿名页的倾向。对于数据库和内存缓存服务,设为 1 或 10 可以显著减少不必要的交换,但不要设为 0,否则在内存压力下可能触发 OOM Killer 而非温和回收。
dirty_ratio 和 dirty_background_ratio 控制脏页回写。默认的 20%/10% 在写入突增时会导致较大的 I/O 停顿。降低到 15%/5% 可以让回写更平滑,代价是略微增加 I/O 频率。对于使用 SSD 的服务器,这个调整通常利大于弊。
vm.min_free_kbytes 保证内核有足够内存用于原子分配。在 64GB 以上的服务器上,默认值可能过小,导致在高负载下分配失败。设为 65536(64MB)是保守且安全的选择。
四、文件系统与 I/O
fs.inotify.max_user_watches = 524288
fs.inotify.max_user_instances = 512
如果你运行了前端构建工具、文件同步服务或 Kubernetes,inotify 限制是常见的“隐形杀手”。默认的 8192 个 watch 在大型项目中极易耗尽,导致 ENOSPC 错误。提升到 524288 可以覆盖绝大多数场景,每个 watch 约消耗 1KB 内核内存,需根据内存容量权衡。
五、如何安全地应用这些参数
不要直接编辑 /etc/sysctl.conf。推荐在 /etc/sysctl.d/ 下创建独立文件,便于管理和回滚:
# /etc/sysctl.d/99-performance.conf
net.core.somaxconn = 32768
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_congestion_control = bbr
net.core.default_qdisc = fq
vm.swappiness = 10
应用并验证:
sysctl --system
sysctl net.ipv4.tcp_congestion_control
关键原则:每次只修改一组相关参数,观察至少一个业务周期(如一天)后再进行下一组。使用 node_exporter + Prometheus 或 sar 记录修改前后的关键指标:连接数、重传率、TIME_WAIT 数量、内存换出量、I/O 等待时间。
六、总结
sysctl 调优的本质是在理解内核行为的基础上,让系统更贴合你的工作负载特征。本文涉及的参数可以归纳为三条主线:
- 网络:扩大队列和缓冲区,选择适合链路的拥塞控制算法,管理好 TIME_WAIT 和连接跟踪。
- 内存:减少不必要的交换,平滑脏页回写,为内核保留安全余量。
- 资源上限:提升文件描述符和 inotify 等硬限制,避免应用层被内核限制卡住。
最后记住:没有度量就没有调优。默认值不是敌人,盲目修改才是。
未经允许不得转载:任鹏个人博客 » Linux 内核参数调优指南:sysctl 中那些真正影响性能的配置


朋友圈点赞图在线生成源码