Linux 内核与网络参数调优:sysctl、文件描述符、TCP 队列与高并发配置
前言
Linux 参数调优不是把网上的一组 sysctl.conf 复制到服务器上。真正有效的调优应该从业务场景出发,先发现瓶颈,再修改参数,最后通过压测和监控验证。
这篇文章围绕常见服务器场景,整理 Linux 内核与网络参数调优思路,重点包括:
- sysctl 配置文件和生效方式;
- 文件描述符、进程数、端口范围;
- TCP 连接队列、SYN Flood、TIME_WAIT;
- 多网卡、ARP、rp_filter;
- swappiness、vm.max_map_count;
- 不建议盲目套用的历史参数;
- 调优前后的验证清单。
如果需要通过压测验证调优效果,可以参考:SysBench 压测实践:CPU、内存、FileIO 与 MySQL OLTP 基准测试指南。如果需要排查命令速查,可以参考:Linux 常用命令速查:磁盘、日志、进程、网络、Docker 与文件排查实践。
调优前先确认场景
不同场景的参数目标不同:
| 场景 | 重点关注 |
|---|---|
| Web / API 服务 | 文件描述符、监听队列、连接复用、TIME_WAIT、端口范围。 |
| 网关 / 反向代理 | somaxconn、tcp_max_syn_backlog、ip_local_port_range、连接跟踪。 |
| 数据库 | 文件描述符、IO、swappiness、THP、内存、连接数。 |
| Elasticsearch / OpenSearch | vm.max_map_count、文件描述符、内存锁定。 |
| 多网卡 / LVS / keepalived | ARP 行为、rp_filter、路由策略。 |
| 容器节点 | 文件描述符、进程数、网络队列、conntrack。 |
建议先回答三个问题:
- 当前瓶颈是 CPU、内存、磁盘、网络还是连接数?
- 是单机瓶颈,还是上游 / 下游 / 数据库瓶颈?
- 修改参数后,用什么指标证明变好了?
sysctl 配置和生效方式
临时修改
临时修改适合验证,重启后失效:
sysctl -w net.core.somaxconn=4096
也可以直接写 /proc:
echo 4096 > /proc/sys/net/core/somaxconn
持久化修改
建议把自定义配置放到 /etc/sysctl.d/:
sudo vi /etc/sysctl.d/99-custom.conf
示例:
net.core.somaxconn = 4096
net.ipv4.tcp_max_syn_backlog = 8192
net.ipv4.ip_local_port_range = 1024 65000
fs.file-max = 2097152
vm.max_map_count = 262144
让所有 sysctl 配置生效:
sudo sysctl --system
只加载某个文件:
sudo sysctl -p /etc/sysctl.d/99-custom.conf
查看当前值:
sysctl net.core.somaxconn
cat /proc/sys/net/core/somaxconn
文件描述符:fs.file-max 与 ulimit
fs.file-max 是系统级文件句柄上限,但应用能打开多少文件,还受进程级限制影响。
查看系统级限制:
sysctl fs.file-max
cat /proc/sys/fs/file-nr
查看当前 shell 限制:
ulimit -n
查看某个进程限制:
cat /proc/<pid>/limits
常见配置:
fs.file-max = 2097152
进程级限制通常通过 /etc/security/limits.conf 或 systemd service 配置:
[Service]
LimitNOFILE=1048576
注意:只改 fs.file-max 不一定解决 Too many open files。如果应用由 systemd 管理,还要检查 service 的 LimitNOFILE。
进程 ID 上限:kernel.pid_max
kernel.pid_max 控制 PID 最大值。高并发短进程或容器节点可能需要适当调大。
kernel.pid_max = 4194303
但大多数服务瓶颈不是 PID 上限,而是线程数、文件描述符、内存或调度开销。不要把它当成通用性能开关。
vm.max_map_count
vm.max_map_count 控制单个进程可拥有的虚拟内存映射区域数量。Elasticsearch、OpenSearch、Logstash 等服务经常要求设置为:
vm.max_map_count = 262144
验证:
sysctl vm.max_map_count
这类参数应该按应用官方要求配置,不建议无理由设置得过高。
swappiness
vm.swappiness 控制内核使用 swap 的倾向,范围通常是 0~100。
常见配置:
vm.swappiness = 1
不建议无脑设置为 0。对于数据库服务器,较低的 swappiness 可以减少活跃数据被换出;但如果完全禁止 swap 或内存规划不足,可能导致 OOM 风险增加。
建议:
- 数据库:低 swappiness,并合理规划内存;
- 普通应用服务器:结合内存容量和 OOM 风险决定;
- Kubernetes / 容器节点:遵循发行版和集群策略。
Magic SysRq:kernel.sysrq
kernel.sysrq 控制 Magic SysRq 功能。需要注意:它不是简单的 0 / 1 / 2 三档。
常见值:
| 值 | 含义 |
|---|---|
0 |
禁用 SysRq。 |
1 |
启用所有 SysRq 功能。 |
| 大于 1 | 按 bitmask 启用部分功能。 |
例如生产环境可以按需启用部分安全功能,而不是直接打开全部能力。配置前建议阅读内核官方 SysRq 文档。
kernel.sysrq = 1
如果安全要求较高,应谨慎开启全部 SysRq。
TCP 监听队列:somaxconn 与 tcp_max_syn_backlog
net.core.somaxconn
net.core.somaxconn 限制 TCP listen backlog 的上限。
net.core.somaxconn = 4096
如果 Nginx、网关、Java 服务或数据库在高并发连接下出现连接排队,可以检查:
sysctl net.core.somaxconn
ss -lnt
注意应用本身也有 backlog 配置,例如 Nginx、Redis、Java 容器等。内核调大但应用 backlog 很小,效果也有限。
net.ipv4.tcp_max_syn_backlog
tcp_max_syn_backlog 控制半连接队列大小。
net.ipv4.tcp_max_syn_backlog = 8192
适用于突发连接多、SYN 队列溢出的场景。需要结合 SYN cookies 和应用连接队列一起看。
SYN Flood 防护:tcp_syncookies
net.ipv4.tcp_syncookies 用于在 SYN 队列溢出时启用 SYN cookies 机制,帮助缓解 SYN Flood。
net.ipv4.tcp_syncookies = 1
一般建议保持开启。它不是提升正常业务性能的参数,而是异常流量下的保护机制。
TIME_WAIT 相关参数
net.ipv4.tcp_max_tw_buckets
tcp_max_tw_buckets 限制系统允许的 TIME_WAIT socket 数量。
net.ipv4.tcp_max_tw_buckets = 200000
如果 TIME_WAIT 很多,先判断原因:
ss -ant state time-wait | wc -l
ss -s
TIME_WAIT 多不一定是问题。它是 TCP 正常关闭连接的一部分。真正需要关注的是:
- 是否导致本地端口耗尽;
- 是否导致内存消耗过大;
- 是否是短连接过多;
- 是否应该在应用层开启连接池或 HTTP keep-alive。
net.ipv4.tcp_tw_reuse
tcp_tw_reuse 允许在特定条件下复用 TIME_WAIT 连接。现代内核中它的行为和旧文章里的描述不完全一样,不建议把它当成通用优化项。
net.ipv4.tcp_tw_reuse = 0
除非明确理解内核版本和业务连接模式,否则建议保持默认或谨慎测试。
tcp_tw_recycle 不应继续使用
旧资料中常见:
net.ipv4.tcp_tw_recycle = 0
这个参数属于旧内核历史参数,后续 Linux 内核已经移除,不应作为现代 Linux 调优项继续推荐。尤其在 NAT 场景下,它曾经容易造成连接异常。
TCP 连接关闭和 KeepAlive
tcp_fin_timeout
tcp_fin_timeout 控制孤儿连接处于 FIN-WAIT-2 的时间。
net.ipv4.tcp_fin_timeout = 15
不要为了“减少连接数”盲目设置过低,可能影响慢连接或复杂网络环境中的正常关闭流程。
tcp_keepalive_time
tcp_keepalive_time 控制 TCP keepalive 探测前的空闲时间。
net.ipv4.tcp_keepalive_time = 600
KeepAlive 是否生效,还取决于应用是否启用 socket keepalive。数据库连接池、RPC 客户端、网关通常还需要应用层心跳和超时配置配合。
本地端口范围:ip_local_port_range
当机器作为大量出站连接客户端时,可能遇到本地临时端口耗尽。
查看端口范围:
sysctl net.ipv4.ip_local_port_range
常见配置:
net.ipv4.ip_local_port_range = 1024 65000
如果仍然耗尽,应优先检查:
- 是否短连接过多;
- 是否连接池没有复用;
- TIME_WAIT 是否异常增长;
- 上游服务是否慢导致连接占用过久。
ARP 与多网卡参数
rp_filter
rp_filter 是反向路径过滤,用于防止源地址欺骗。常见取值:
| 值 | 含义 |
|---|---|
0 |
关闭。 |
1 |
严格模式。 |
2 |
松散模式。 |
示例:
net.ipv4.conf.all.rp_filter = 0
net.ipv4.conf.default.rp_filter = 0
但这不应作为通用推荐。只有在多网卡、策略路由、LVS、非对称路由等场景下,才需要考虑关闭或改为 loose mode。普通单网卡服务器可以保留发行版默认值。
arp_announce
arp_announce 常用于多网卡、多 IP、VIP、LVS 场景,减少 ARP flux 问题。
net.ipv4.conf.all.arp_announce = 2
net.ipv4.conf.default.arp_announce = 2
如果服务器只有普通单网卡,不一定需要修改。
neigh.default.gc_stale_time
net.ipv4.neigh.default.gc_stale_time 影响邻居缓存项的过期时间。
net.ipv4.neigh.default.gc_stale_time = 120
除非遇到 ARP 缓存、网关漂移、多网卡等问题,否则不建议盲目调整。
IPv6 是否禁用
旧配置里常见:
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
现在不建议把禁用 IPv6 当成默认优化。是否禁用应取决于:
- 业务是否使用 IPv6;
- 云厂商 VPC 是否支持 IPv6;
- 安全组、防火墙是否覆盖 IPv6;
- 应用监听是否包含 IPv6 地址。
如果只是为了避免误监听,可以优先从应用监听地址、防火墙、安全组层面控制。
消息队列参数:kernel.msgmnb / kernel.msgmax
kernel.msgmnb = 65536
kernel.msgmax = 65536
这类 System V IPC 消息队列参数只有在应用确实使用对应机制时才有意义。大多数 Java Web、Nginx、MySQL 场景不需要专门调整。
网络缓冲区参数
常见参数:
net.core.rmem_default = 8388608
net.core.wmem_default = 8388608
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
这些参数影响 socket 接收 / 发送缓冲区上限。适用于高吞吐、长肥网络、网关、代理、流媒体等场景。普通内网业务不一定需要调大。
推荐配置模板
下面模板只能作为起点,不能直接替代压测和监控。
Web / API 服务
fs.file-max = 2097152
net.core.somaxconn = 4096
net.ipv4.tcp_max_syn_backlog = 8192
net.ipv4.tcp_syncookies = 1
net.ipv4.ip_local_port_range = 1024 65000
net.ipv4.tcp_fin_timeout = 15
net.ipv4.tcp_keepalive_time = 600
还需要配合:
- systemd
LimitNOFILE; - Nginx / Java / Tomcat / Netty backlog;
- 应用连接池;
- 负载均衡和限流策略。
Elasticsearch / OpenSearch 节点
vm.max_map_count = 262144
fs.file-max = 2097152
vm.swappiness = 1
还要配合应用官方要求,例如 JVM heap、memlock、文件描述符、磁盘水位线等。
网关 / 代理节点
fs.file-max = 2097152
net.core.somaxconn = 8192
net.ipv4.tcp_max_syn_backlog = 16384
net.ipv4.ip_local_port_range = 1024 65000
net.ipv4.tcp_syncookies = 1
如果连接数非常高,还要关注 conntrack、NAT、端口耗尽、上游连接池和 keep-alive。
不建议盲目套用的参数
| 参数 | 建议 |
|---|---|
net.ipv4.tcp_tw_recycle |
已是历史参数,不应继续推荐。 |
vm.swappiness = 0 |
不建议无脑设置,可能增加 OOM 风险。 |
net.ipv6.conf.*.disable_ipv6 = 1 |
不应作为默认优化,按业务和安全策略决定。 |
rp_filter = 0 |
只在多网卡 / 非对称路由等场景谨慎使用。 |
过大的 fs.file-max |
系统级调大不代表进程限制已调大,还会掩盖应用泄漏问题。 |
过低的 tcp_fin_timeout |
可能影响正常连接关闭。 |
调优验证清单
调优前后建议记录:
# 内核参数
sysctl -a > sysctl-before.txt
sysctl -a > sysctl-after.txt
# 连接状态
ss -s
ss -ant | awk '{print $1}' | sort | uniq -c
# 监听端口
ss -lntp
# 文件描述符
ulimit -n
cat /proc/sys/fs/file-nr
cat /proc/<pid>/limits
# 系统负载
uptime
vmstat 1
top
# 磁盘 IO
iostat -x 1
# 网络
sar -n TCP,ETCP 1
ip -s link
再配合 SysBench、业务压测或线上监控,对比:
- TPS / QPS 是否变化;
- P95 / P99 延迟是否变化;
- CPU、IO、网络是否成为新瓶颈;
- 错误率是否下降;
- 连接队列溢出、端口耗尽、文件句柄耗尽是否消失。
小结
Linux 参数调优的核心原则是:
- 先定位瓶颈;
- 再按场景修改参数;
- 修改前后保留配置快照;
- 用压测和监控验证;
- 不盲目复制历史配置,尤其是已废弃或有副作用的网络参数。
调优不是一次性操作,而是容量规划、监控告警、压测验证和应用架构一起配合的过程。