优化 Nginx 文件描述符限制需要同时调整操作系统层面的 ulimit 限制和 Nginx 配置文件中的 worker_rlimit_nofile 及 worker_connections 参数。适用高并发反向代理场景,风险在于过高的限制可能增加内核内存开销。
先说结论:解决 Nginx 高并发文件描述符不足问题,必须同步提升系统级限制和 Nginx 进程级限制,否则配置无法生效。
- 先定位:检查当前 Nginx 进程的实际文件描述符上限,确认是否命中 1024 默认值。
- 先做:修改/etc/security/limits.conf 系统配置和 Nginx 配置文件,若使用 Systemd 需额外覆盖服务限制。
- 再验证:通过/proc 目录查看进程 limits 文件,确认新限制已加载且无重启报错。
命令速用版
以下命令用于快速查看当前限制状态和重载配置,执行前请确认拥有 root 权限。
查看当前 shell 文件描述符限制:
ulimit -n
查看 Nginx 主进程 PID:
cat /run/nginx.pid
查看 Nginx 进程实际限制(替换<pid>为实际进程号):
cat /proc/<pid>/limits | grep "open files"
测试 Nginx 配置并重载:
nginx -t && nginx -s reload
为什么会这样
Linux 系统将网络连接视为文件,每个并发连接至少消耗一个文件描述符,默认限制通常过低。
Nginx 在高并发反向代理场景下,每个客户端连接都需要占用文件描述符,若作为代理上游还需要额外的描述符连接后端服务。操作系统默认的单进程文件描述符限制通常为 1024,当并发连接数超过此值时,Nginx 会拒绝新连接并在错误日志中记录"too many open files"。仅修改 Nginx 配置而不修改系统限制,或者仅修改系统限制而未正确传递给 Nginx 进程,都会导致优化无效。
分步处理
按顺序执行以下步骤,确保系统层和应用层限制同步提升。
步骤 1:调整系统级限制
编辑/etc/security/limits.conf 文件,添加或修改以下行,适用所有用户或特定 Nginx 运行用户。
* soft nofile 65535
* hard nofile 65535
适用场景:所有基于 PAM 登录的会话。风险边界:设置过大可能消耗更多内核内存,需根据物理内存调整。
步骤 2:调整 Nginx 配置限制
在 nginx.conf 的 http 块或 main 块中添加 worker_rlimit_nofile 指令,并在 events 块中设置 worker_connections。
worker_rlimit_nofile 65535;
events {
worker_connections 65535;
}
操作动作:worker_connections 不能超过 worker_rlimit_nofile。验证结果:nginx -t 测试通过。
步骤 3:处理 Systemd 服务限制
若 Nginx 通过 Systemd 启动,/etc/security/limits.conf 可能不生效,需创建覆盖配置。
执行systemctl edit nginx,输入以下内容:
[Service]
LimitNOFILE=65535
适用场景:CentOS 7+/Ubuntu 16.04+ 等使用 Systemd 的系统。风险边界:修改后必须 reload daemon 并 restart 服务。
步骤 4:重载服务
执行systemctl daemon-reload和systemctl restart nginx使所有限制生效。
怎么验证是否生效
通过查看进程状态和日志确认配置已加载且无错误。
检查点 1:进程限制文件
获取 Nginx 主进程 PID,查看/proc/<pid>/limits 文件中"Max open files"行的 soft 和 hard 值是否已变为设定值。
检查点 2:错误日志
观察 Nginx error.log,确认高并发期间不再出现"too many open files"报错。
检查点 3:连接状态
使用ss -s或netstat -n | wc -l观察当前连接数,确认连接数上升时服务未拒绝请求。
常见坑
列出容易出错的点,提醒哪些场景应该谨慎。
Systemd 忽略 limits.conf:现代 Linux 发行版使用 Systemd 管理服务,/etc/security/limits.conf 仅对登录 shell 有效,服务启动需通过 LimitNOFILE 指定。
软限制与硬限制不匹配:worker_rlimit_nofile 不能超过硬限制,否则 Nginx 启动失败或自动降级。
未重启主进程:仅 reload 配置可能不继承新的系统限制,修改系统级限制后建议 restart Nginx 主进程。
内核级文件总数限制:除单进程限制外,还需检查/proc/sys/fs/file-max,确保系统总文件描述符充足。
常见问题
worker_rlimit_nofile 和 worker_connections 有什么区别?
worker_rlimit_nofile 是 Nginx 进程能打开的最大文件描述符数,worker_connections 是每个 worker 进程能处理的最大连接数。
修改 limits.conf 后为什么 Nginx 限制没变?
因为 Nginx 通过 Systemd 启动时不读取 limits.conf,需要在 systemd 服务文件中配置 LimitNOFILE 参数。
文件描述符限制设置得越高越好吗?
不是,过高的限制会占用更多内核内存,应根据实际并发需求和服务器物理内存合理设置。
如何计算需要的文件描述符数量?
公开资料中没有看到可靠的量化数据,通常建议预留 20% 余量,每个反向代理连接至少消耗 2 个描述符(客户端 + 后端)。
参考来源
Nginx Official Documentation, "Core directives", https://nginx.org/en/docs/ngx_core_module.html
Nginx Official Documentation, "Events Module", https://nginx.org/en/docs/ngx_events_module.html
Linux Man Pages, "limits.conf", https://man7.org/linux/man-pages/man5/limits.conf.5.html
Systemd Documentation, "systemd.exec", https://www.freedesktop.org/software/systemd/man/systemd.exec.html