Linux 高并发服务器参数调优
Table of Contents
1. 文件描述符数量限制
文件描述符(FD)数量是限制并发连接数的关键因素之一。使用 ulimit -n 可以查看当前用户可以打开的最大 FD 数量,默认通常是 1024——这意味着单个进程最多同时处理 1024
个连接。对外开放的服务器应当扩大这个限制。
FD 限制分三层:内核全局上限、内核单进程上限、用户级限制。
1.1. 内核参数
# /etc/sysctl.d/90-fd.conf # 仅在默认值不够时启用,以下数值为示例 # fs.file-max = 2000000 # fs.nr_open = 2000000
fs.file-max:内核全局最大文件描述符数量。现代发行版通常按内存自动计算默认值,一般已经很大。可以用cat /proc/sys/fs/file-max查看当前值,只有当默认值不满足需求时才需要手动设置。fs.nr_open:单个进程可以打开的最大文件数量,默认值是 \(2^{20}=1048576\) 。它是ulimit -n的天花板——用户级 hard limit 不能超过这个值。如果你需要把 nofile 设置到超过 1048576,才需要先提高fs.nr_open。
验证:
sysctl fs.file-max fs.nr_open cat /proc/sys/fs/file-nr # 已分配 / 未使用 / 上限
1.2. 用户级限制(PAM)
# /etc/security/limits.d/90-nofile.conf * soft nofile 600000 * hard nofile 600000 root soft nofile 600000 root hard nofile 600000
soft 是实际生效的限制——进程打开的 FD 数量达到 soft 后,再打开会直接失败(返回
EMFILE ),而不是仅仅发出警告。 hard 是 soft 的上限,普通用户只能降低 hard
而不能提高。将两者设为相同值意味着进程启动后就以最大额度运行。
注意:
/etc/security/limits.conf可能被系统更新覆盖,建议写到/etc/security/limits.d/90-nofile.conf。- 通配符
*不匹配 root 用户,所以上例额外给出了root的配置。 - 有时还需要增加
nproc(最大进程数),但现代程序通常使用线程或异步 I/O,不太会触及这个限制。
1.3. systemd 服务限制
PAM limits 对 systemd 管理的服务 不生效 。systemd 启动服务时不走 PAM 登录流程,因此 /etc/security/limits.conf 里的配置对 Nginx、MySQL 等 daemon 无效。
对单个服务设置:
systemctl edit nginx # 在打开的编辑器中添加: # [Service] # LimitNOFILE=600000 systemctl daemon-reload systemctl restart nginx
对所有 systemd 服务设置全局默认:
# /etc/systemd/system.conf DefaultLimitNOFILE=600000
- 如果修改的是某个 unit 或 drop-in,执行
systemctl daemon-reload后重启对应服务。 - 如果修改的是
/etc/systemd/system.conf,执行systemctl daemon-reexec,然后重启受影响的服务,或直接重启系统。 - 最后用
cat /proc/<pid>/limits验证实际生效值。
1.4. 如何估算 nofile
nofile 不该拍脑袋设一个大数,最好按业务形态粗略估算:
nofile >= 监听 socket + 峰值客户端连接数 + 峰值上游连接数 + 日志/临时文件 + 安全余量
对于单进程 event-loop 程序,最关键的是“客户端连接 + 上游连接”。反向代理会同时占用客户端和后端连接两侧的 FD,因此比纯 Web 服务更容易打满。
举个例子:如果 Nginx 峰值保持 100000 个客户端 keepalive 连接,同时与上游维持 20000
个 keepalive 连接,再加上监听 socket、日志文件和少量临时文件,那么 nofile 至少应在 120000 以上。通常再预留 20% 到 50% 的安全余量,设置到 150000 到 200000 会更稳妥。
2. 网络优化
以下参数主要面向高并发、大量短连接的场景(反向代理、API 网关、压测客户端等)。普通服务器不一定都需要调整——修改前请确认你的瓶颈确实在这里。
2.1. TIME_WAIT 相关
net.ipv4.tcp_tw_reuse = 1
tcp_tw_reuse:允许将 TIME_WAIT 状态的连接复用于新的 出站 连接。现代内核(约 2020 年后)默认值是2(仅对 loopback 生效)。设为1对所有出站连接启用,适合需要大量主动外连的场景(如反向代理连后端)。对于纯粹接受入站连接的服务(如 Web 服务器直接面向客户端),该参数帮助不大。- 关于
tcp_tw_recycle:该参数在 Linux 4.12 后 已被移除 。在 NAT 环境下会导致连接失败,不应再出现在配置中。
关于 TIME_WAIT 本身:TIME_WAIT 状态是 TCP 协议的正常机制——它防止旧连接的延迟报文被新连接误收。不要试图"消灭"所有 TIME_WAIT,而是通过 tcp_tw_reuse 让内核在安全的前提下复用它们。
2.2. 连接保活与超时
net.ipv4.tcp_keepalive_time = 600 net.ipv4.tcp_fin_timeout = 30
tcp_keepalive_time:TCP 发送 keepalive 探测的间隔,默认 7200 秒(2 小时)。改为 600 秒(10 分钟)可以更快发现死连接并回收资源。仅对启用了SO_KEEPALIVE的连接生效。副作用是增加少量网络流量。tcp_fin_timeout:orphaned 连接(已被应用关闭引用的连接)在 FIN_WAIT_2 状态的超时时间,默认 60 秒。高并发短连接场景下可以缩短到 30 秒,加速连接回收。
2.3. 端口范围
net.ipv4.ip_local_port_range = 10000 65000
本机可用的临时端口号范围,默认通常是 32768 60999 。对于反向代理(如 Nginx 连后端)或压测客户端这类需要大量主动外连的角色,扩大范围可以支撑更多并发连接。纯粹接受入站连接的服务一般不需要调整。
2.4. 缓冲区
net.ipv4.tcp_rmem = 4096 87380 16777216 net.ipv4.tcp_wmem = 4096 65536 16777216 net.core.rmem_default = 262144 net.core.wmem_default = 262144 net.core.rmem_max = 16777216 net.core.wmem_max = 16777216
tcp_rmem/tcp_wmem:TCP 接收/发送缓冲区的「最小值 默认值 最大值」(字节)。内核会在这个范围内自动调整(autotuning)。最大值设得太小会限制高带宽、长距离传输的吞吐量(BDP 受限)。上述值适合万兆网络环境;普通千兆服务器最大值设到4194304(4 MB)通常也够用。rmem_max/wmem_max:内核允许的套接字缓冲区上限。需要不低于tcp_rmem/tcp_wmem的最大值,否则 TCP autotuning 会被截断。rmem_default/wmem_default:非 TCP 套接字(如 UDP)的默认缓冲区大小。
2.5. 连接队列
net.core.somaxconn = 65535 net.core.netdev_max_backlog = 65535
somaxconn:=listen()= 的 backlog 上限。Linux 5.4 起默认值已从 128 提升为 4096。如果你的内核 ≥ 5.4 且并发不超过数千,可以不改。高并发场景建议设为 65535。注意应用层也要配合设置(如 Nginx 的listen ... backlog=65535;)。netdev_max_backlog:网卡收包后、内核协议栈处理前的缓冲队列长度,默认 1000。高流量网卡可以适当加大以减少丢包。
2.6. 默认已开启,无需手动设置
net.ipv4.tcp_window_scaling:支持超过 64KB 的 TCP 窗口(RFC 1323),自 Linux 2.6.8 起默认开启。除非有特殊兼容性需求,不需要写进配置。
3. 方便调试
# /etc/sysctl.d/90-debug.conf kernel.core_uses_pid = 1
kernel.core_uses_pid:core dump 文件名添加 PID 后缀,防止多个进程的 core 文件互相覆盖。
如果需要完整的 core dump 支持,还需要配合:
# 允许生成 core 文件(默认可能为 0,即禁止) ulimit -c unlimited # 自定义 core 文件路径和命名格式 echo '/var/coredumps/core.%e.%p.%t' | sudo tee /proc/sys/kernel/core_pattern sudo mkdir -p /var/coredumps # 如果使用 systemd-coredump(多数现代发行版的默认方式) # core dump 会被 journald 管理,用 coredumpctl 查看 coredumpctl list
4. 汇总
4.1. sysctl 配置
# /etc/sysctl.d/90-tuning.conf # --- 文件描述符 --- # 仅在默认值不够时取消注释 # fs.file-max = 2000000 # fs.nr_open = 2000000 # --- TCP TIME_WAIT --- net.ipv4.tcp_tw_reuse = 1 # --- 连接保活与超时 --- net.ipv4.tcp_keepalive_time = 600 net.ipv4.tcp_fin_timeout = 30 # --- 端口范围(主动外连场景) --- net.ipv4.ip_local_port_range = 10000 65000 # --- 缓冲区 --- net.ipv4.tcp_rmem = 4096 87380 16777216 net.ipv4.tcp_wmem = 4096 65536 16777216 net.core.rmem_default = 262144 net.core.wmem_default = 262144 net.core.rmem_max = 16777216 net.core.wmem_max = 16777216 # --- 连接队列 --- net.core.somaxconn = 65535 net.core.netdev_max_backlog = 65535 # --- 调试 --- kernel.core_uses_pid = 1
应用配置:
sudo sysctl --system # 验证 sysctl -a | grep -E 'somaxconn|file-max|tw_reuse'
4.2. 用户级 FD 限制
# /etc/security/limits.d/90-nofile.conf * soft nofile 600000 * hard nofile 600000 root soft nofile 600000 root hard nofile 600000
4.3. systemd 服务 FD 限制
# /etc/systemd/system.conf(全局默认) DefaultLimitNOFILE=600000
或对单个服务:
systemctl edit nginx # 添加 [Service] LimitNOFILE=600000 systemctl daemon-reload systemctl restart nginx
修改单个服务后执行 systemctl daemon-reload 并重启对应服务;修改
/etc/systemd/system.conf 后执行 systemctl daemon-reexec ,再重启受影响的服务或直接重启系统。
5. 验证清单
# 文件描述符 ulimit -n # 当前用户 soft limit ulimit -Hn # 当前用户 hard limit cat /proc/sys/fs/file-nr # 系统级 FD 使用情况(已分配 / 未使用 / 上限) cat /proc/<pid>/limits # 特定进程的实际限制 # 网络参数 sysctl net.ipv4.tcp_tw_reuse sysctl net.core.somaxconn ss -s # TCP 连接状态统计 # core dump ulimit -c # 是否允许生成 core cat /proc/sys/kernel/core_pattern