要让nginx稳定支撑高并发,必须打通文件描述符四层:nginx配置层(worker_rlimit_nofile ≥ worker_connections×2.5)、用户级ulimit(/etc/security/limits.conf+systemd limitnofile)、系统级fs.file-max(≥峰值×1.5~2倍)、内核网络层(somaxconn=65535、listen backlog显式设置、tcp_tw_reuse=1)。

要让 Nginx 在生产环境稳定支撑高并发,文件描述符(file descriptor, fd)必须全程打通:从 Nginx 配置、Linux 用户级限制、系统级上限,到内核网络队列,四层缺一不可。只改 worker_connections 而不调系统限制,必然在压测或流量高峰时爆出 Too many open files 错误——这不是配置失误,而是资源链路断裂。
一、Nginx 配置层:worker_rlimit_nofile 与 worker_connections 必须配比
这两个参数不是并列关系,而是主从约束:
-
worker_connections是每个 Worker 进程能处理的并发连接数(含客户端连接、后端代理连接、日志句柄、临时文件等),设为 65535 是常见起点 -
worker_rlimit_nofile是 Nginx 主进程为每个 Worker 预分配的 fd 上限,必须 ≥worker_connections × 2.5(留足缓冲,防突发开销) - 例如:
worker_processes auto(8 核即 8 个 Worker),worker_connections 65535→ 单 Worker 最高需约 16 万 fd →worker_rlimit_nofile至少设为 200000 - 若未显式设置
worker_rlimit_nofile,Nginx 将继承启动用户的 ulimit 值,极易成为静默瓶颈
二、系统用户级限制:ulimit 必须对 systemd 服务生效
Linux 对单进程的 fd 限制由 ulimit -n 控制,但该值必须在 Nginx 启动前就固化,否则无效:
- 编辑
/etc/security/limits.conf,添加两行(不能只写 soft 或 hard):
* soft nofile 200000
* hard nofile 200000 - systemd 服务默认忽略 limits.conf,必须额外创建覆盖配置:
mkdir -p /etc/systemd/system/nginx.service.d
新建/etc/systemd/system/nginx.service.d/override.conf,写入:
[Service]
LimitNOFILE=200000 - 重载配置并重启:
systemctl daemon-reload && systemctl restart nginx - 验证是否生效:
cat /proc/$(pgrep nginx)/limits | grep "Max open files",应显示200000
三、系统全局级限制:fs.file-max 要留足余量
这是整个 Linux 系统可分配的 fd 总数,所有进程共享。它必须显著高于 Nginx 所需峰值,还要预留空间给 SSH、监控、日志轮转等其他服务:
- 临时调整:
sysctl -w fs.file-max=4194304(400 万是中大型服务常用值) - 永久生效:在
/etc/sysctl.conf中追加:
fs.file-max = 4194304 - 执行
sysctl -p加载;检查:cat /proc/sys/fs/file-max - 建议值参考:Nginx 需求峰值 × 1.5~2 倍,避免被其他进程挤占导致随机 fd 分配失败
四、内核网络层:somaxconn 和 TCP 回收必须同步对齐
文件描述符不仅用于已建立连接,还承载“等待 accept”的半连接和 TIME_WAIT 状态套接字。忽视这一层,会出现连接超时、SYN 丢包等隐性故障:
-
net.core.somaxconn控制内核 listen 队列长度,默认常为 128,远低于 Nginx 并发能力 → 设为 65535 - Nginx 的
listen指令需显式声明 backlog:
listen 80 backlog=65535;(否则仍走内核默认值) - 启用 TIME_WAIT 复用,缓解短连接风暴:
net.ipv4.tcp_tw_reuse = 1(仅对客户端为本机发起的连接有效) - 如需更激进回收(如 API 网关),可加:
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_max_tw_buckets = 2000000











