Linux内核参数sysctl.conf极限高并发调优实战

高并发场景下默认内核参数是性能瓶颈的核心。本文直接拆解 net.ipv4.tcp_tw_reuse、vm.swappiness、fs.file-max 等关键参数的调优逻辑、推荐值、风险与验证方法,帮助你写出一份可上线的 /etc/sysctl.conf 配置。

Linux内核参数sysctl.conf极限高并发调优实战
封面图:ZuCDN · ZuCDN 原创

为什么默认参数扛不住高并发

当你把一台 Linux 服务器推到每秒数万连接时,操作系统默认的内核参数就像一条乡间小道——TIME_WAIT 堆积如山,连接队列被填满,内存回收滞后导致 OOM。这些问题不是靠增加硬件就能解决的,根源是内核没有为高并发场景优化。sysctl.conf 调优就是把这些道路拓宽成八车道,但每一条车道都需要你知道在什么速度下会翻车。

调优前的准备工作

在改任何参数之前,先确认三件事:你的 Linux 内核版本(uname -r),峰值 QPS 或并发连接数预估,以及是否有监控系统(如 Prometheus + node_exporter)。所有参数修改后必须用 sysctl -p 立即生效,但建议先在预发布环境压测至少 30 分钟,观察 CPU、内存、网络丢包率以及用户态错误日志。

需要特别注意的是:不要直接拷贝网上的参数。不同硬件、内核版本、业务模型(短连接 vs 长连接、HTTP vs RPC)对参数的反应差异巨大。下面每个参数我都会说明适用环境与风险。

核心网络参数调优

1. TIME_WAIT 与连接复用

高并发短连接(如 HTTP/1.1 无 keepalive)会制造大量 TIME_WAIT 套接字。默认的 60 秒超时意味着每秒 1 万新连接时,同时存在 60 万个 TIME_WAIT 套接字,直接吃掉端口和内存。

  • net.ipv4.tcp_tw_reuse = 1:允许将 TIME_WAIT 状态的连接用于新连接。前提是启用时间戳(默认开启)。这个参数没有副作用,推荐在客户端或反向代理上开启,服务端开启也安全,但注意如果 NAT 环境可能导致问题。
  • net.ipv4.tcp_tw_recycle = 0强烈不建议开启。该参数依赖对端时间戳,在 NAT 或负载均衡环境中会导致丢包和连接失败。Linux 4.12 以后已移除该参数,如果你还在用旧内核,直接设为 0。
  • net.ipv4.tcp_fin_timeout = 15:减少 FIN-WAIT-2 状态的超时时间,默认 60 秒。对于快速释放资源有效,但某些协议可能因对端不主动关闭而提前断开,测试后调整。

2. TCP 连接队列积压

当应用层来不及 accept 连接时,半连接队列和全连接队列会溢出。参数如下:

  • net.core.somaxconn = 65535:listen 的最大 backlog,默认 128。应用层(如 Nginx、Tomcat)也需设置对应值,否则内核参数再大也没用。
  • net.ipv4.tcp_max_syn_backlog = 65535:SYN 半连接队列长度,防止 SYN 洪水。
  • net.core.netdev_max_backlog = 50000:每个网络接口接收数据包的最大队列。如果频繁出现 listen queue overflow 错误,可继续上调。

3. 端口范围与 TIME_WAIT 回收

  • net.ipv4.ip_local_port_range = 1024 65535:扩大临时端口范围,减轻端口耗尽压力。注意不要低于 1024,避免与特权端口冲突。
  • net.ipv4.tcp_max_tw_buckets = 2000000:系统能同时保持的 TIME_WAIT 最大数量,超出后系统会“砍掉”多余的 TIME_WAIT 连接并记录日志。这不是解决问题,只是防止内核内存被耗尽。

内存与文件句柄调优

4. 内核态 vs 用户态内存

  • vm.max_map_count = 655300:限制进程能拥有的最大内存映射区域数。高并发应用(尤其是 Elasticsearch、Java 应用)容易超过默认值,导致 mmap 失败。一般设为 655300 或更高。
  • vm.swappiness = 1:控制内核使用 swap 的积极程度。默认 60,在高并发场景下宁可 OOM 也不要频繁 swap,因为 swap 的延迟会杀死性能。设置为 1 表示“不到万不得已不用 swap”。如果服务器内存充足且业务对延迟敏感,甚至可以设为 0。
  • vm.min_free_kbytes = 524288:保留 512MB 空闲内存防止系统在内存紧张时卡死。单位是 KB,根据物理内存大小调整(建议为总内存的 0.5%~1%)。

5. 文件句柄与连接数

  • fs.file-max = 2097152:系统级最大文件句柄数,决定了能打开的最大 socket 数量(每个连接一个 fd)。单机并发 50 万连接时,至少需要 50 万 + 预留。通常设为 200 万。
  • fs.nr_open = 2097152:单个进程能打开的最大文件句柄数,必须 ≥ ulimit -n 中设置的值。如果两者不匹配,即使 ulimit 配置了高值也无法生效。

其他关键参数

6. 网络缓冲区与 TCP RTT

  • net.core.rmem_default = 262144net.core.wmem_default = 262144:默认 Socket 读写缓冲 256KB。
  • net.core.rmem_max = 16777216net.core.wmem_max = 16777216:最大 16MB,允许 TCP 窗口缩放。
  • net.ipv4.tcp_rmem 和 tcp_wmem:三段式参数(min, default, max),建议调整为 4096 87380 16777216,其中默认值 87380 字节是经典值,对于高带宽长肥网络可能需要更大。
  • net.ipv4.tcp_slow_start_after_idle = 0:关闭空闲连接后的慢启动。对于保持连接的 RPC 服务或 WebSocket,避免每次空闲后重走拥塞窗口。

7. RST 与 SYN Flood 防护

  • net.ipv4.tcp_abort_on_overflow = 1:当全连接队列满时,直接 RST 新连接而不是丢弃。虽然粗暴,但可以让客户端快速重试,避免超时。如果业务容忍少量丢包,推荐开启。
  • net.ipv4.tcp_syncookies = 1:默认开启,SYN Flood 时启用 cookie。保持开启。

验证调优效果与回滚策略

所有参数改完后,执行 sysctl -p,然后观察三个指标:

  • ss -s 查看 TCP 状态分布,TIME_WAIT 数量应明显减少。
  • cat /proc/net/stat/tcp_tw 可看到 TW 回收情况(部分内核不支持)。
  • 应用层的错误日志:Too many open filesconnection reset by peerlisten queue overflow 是否消失。

如果压测后系统出现挂死、大量 backlog 溢出或者应用超时增加,可以使用 sysctl -w 临时恢复特定参数,或者直接重启加载默认配置。更稳妥的做法是在 /etc/sysctl.d/ 下创建单独的配置文件(如 99-highload.conf),方便回滚时仅删除该文件并重载。

特别注意:tcp_tw_recycle 和 tcp_tw_reuse 不要一起开启,这两个参数在 4.12 版内核后已被标记为废弃或移除,如果你还在用旧内核,务必关闭 tcp_tw_recycle。

一个可参考的完整配置示例

# 网络核心
net.core.somaxconn = 65535
net.core.netdev_max_backlog = 50000
net.core.rmem_default = 262144
net.core.wmem_default = 262144
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216

# TCP
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 15
net.ipv4.tcp_max_syn_backlog = 65535
net.ipv4.ip_local_port_range = 1024 65535
net.ipv4.tcp_max_tw_buckets = 2000000
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216
net.ipv4.tcp_slow_start_after_idle = 0
net.ipv4.tcp_abort_on_overflow = 1
net.ipv4.tcp_syncookies = 1

# 内存 & 文件句柄
vm.swappiness = 1
vm.min_free_kbytes = 524288
vm.max_map_count = 655300
fs.file-max = 2097152
fs.nr_open = 2097152

以上配置适用于四层或七层代理、API 网关、高并发 Web 服务器,对数据库服务器(如 MySQL、PostgreSQL)需要调整部分参数(如不要开启 tcp_abort_on_overflow,因为数据库更依赖可靠交付)。

本文没有说的参数(为什么)

有很多文章推荐 net.ipv4.tcp_low_latency、tcp_sack、tcp_dsack 等,这些参数在现代内核中已被合理缺省值覆盖,或者收益很小且难以测试。调优的目标是消除明显瓶颈,而不是盲目优化所有参数。如果基本参数调优后仍然有性能问题,应该优先检查应用层并发模型、epoll 使用是否高效、是否缺页中断过高,而不是继续堆内核参数。

总结

内核参数调优不是玄学,而是一份针对业务特征的清单。本文列出的参数涵盖了 TIME_WAIT 回收、连接队列放大、内存换出抑制、文件句柄上限四个维度。核心原则是:每次只改 2~3 个参数,压测确认效果,监控异常指标。只有在理解每个参数为什么有效、什么情况下无效之后,你才真正拥有一条扛得住极限并发的服务器。

延伸阅读