📖 背景 大屏平稳运行。某天访问量稍微大了一点。Nginx 突然开始狂报 502 Bad Gateway。查 error.log,满屏红字:Too many open files。Flask 后端明明活着,但 Nginx 就是连不上。
🔍 原因 小学生版解释:Linux 系统是个发号牌的门卫。每个文件、每个网络连接,都要发一个号牌(文件句柄)。 默认情况下,门卫手里只有 1024 个号牌。Nginx 既要接访客(连接),又要看日志(文件),还要连 Flask(代理),还得转发静态资源。 人一多,号牌发完了。新来的人只能吃闭门羹(报错)。 排查命令:
bash
ulimit -n
# 输出 1024
🛠 解决 需要分两处改:系统层 和 Nginx 自身层。
- 系统层放号牌 修改 /etc/security/limits.conf:
markdown
* soft nofile 65535
* hard nofile 65535
修改 systemd 全局配置 /etc/systemd/system.conf:
ini
DefaultLimitNOFILE=65535
- Nginx 层加配 修改 nginx.conf,在开头加上:
ini
worker_rlimit_nofile 65535;
events {
worker_connections 65535;
}
✅ 验证效果 重启 Nginx。 查 Nginx 主进程的限额:
bash
cat /proc/$(pgrep nginx | head -1)/limits | grep "open files"
预期输出:Max open files 65535 65535 files。 访问大屏,502 消失,系统顶住了并发。
💣 三个坑 只改 limits.conf 没用:如果你是用 systemctl restart nginx 启动的,systemd 会覆盖 limits.conf。必须改 /etc/systemd/system.conf。
Nginx 两个参数不匹配:worker_connections 不能大于 worker_rlimit_nofile。否则 Nginx 启动直接报错。
reload 不生效:改 ulimit 必须 restart,光 nginx -s reload 没用,因为进程 PID 没变,号牌数量不会重新分配。