ulimit -Hn 不能单独解决高并发句柄故障,必须同步配置 limits.conf(含PAM支持)、systemd服务LimitNOFILE、系统fs.file-max,并验证进程实际limits值,否则硬限制不生效。

直接用 ulimit -Hn 调硬限制不能解决高并发Web服务的句柄故障——因为硬限制本身不是“调高就能用”的开关,它必须和系统级、服务启动方式、实际进程继承关系匹配,否则改了也白改。
先确认是不是真卡在硬限制上
很多报错“Too many open files”的服务,表面看 ulimit -n 是65535,但实际进程的硬限制可能仍是1024。关键要看进程自己生效的值:
- 查当前 Shell 的软/硬限制:
ulimit -Sn和ulimit -Hn - 查 Web 服务进程(如 nginx 或 java)的真实限制:
cat /proc/$(pgrep nginx)/limits | grep "Max open files" - 如果输出里 hard limit 远低于预期(比如还是 4096),说明服务没继承你设的值
硬限制生效的前提是用户级配置被正确加载
/etc/security/limits.conf 是核心,但容易配错或不生效:
- 必须写全两行:
* soft nofile 65535和* hard nofile 1048576(硬限建议 ≥ 软限,且留余量) - 若服务以特定用户运行(如 www-data、nginx),应明确写用户名,别只靠 * 通配
- 确保
/etc/pam.d/common-session包含session required pam_limits.so,否则 PAM 不读 limits.conf - SSH 新建会话才加载新 limits;已有终端需重新登录,
ulimit -Hn手动设仅对当前 shell 有效
systemd 服务必须单独配 LimitNOFILE
从 systemd 219 开始,limits.conf 对 systemctl start 启动的服务基本失效:
- 编辑服务文件,例如
/etc/systemd/system/nginx.service - 在
[Service]段下添加:LimitNOFILE=1048576(同时设软硬限)或LimitNOFILE=65535:1048576(软:硬) - 执行:
sudo systemctl daemon-reload && sudo systemctl restart nginx - 重启后立刻验证:
cat /proc/$(pgrep nginx)/limits | grep "Max open files",必须看到 hard 值是你设的数
硬限制不是越大越好,得配合系统资源
盲目设 hard nofile 1000000 可能引发内存压力甚至 OOM:
- 每个文件描述符内核约占 1KB 内存,100 万句柄 ≈ 额外占用 1GB 内核内存
- 建议按公式粗估:
free -g | awk '/Mem:/ {print $2 * 10000}'(每 GB 内存配约 1 万个句柄) - 同步检查并调大系统总上限:
fs.file-max至少为所有服务 hard 限之和 × 1.5,写入/etc/sysctl.conf并sysctl -p - Java 类服务还需额外确认:JVM 是否识别到新限制(
java -XX:+PrintFlagsFinal -version | grep MaxOpenFiles),必要时加-XX:MaxOpenFiles=65536(JDK12+)











