根本原因是ulimit -u(用户级进程/线程总数)与/proc/sys/kernel/pid_max(系统级pid上限)未同步调大,导致高并发时pid耗尽;必须同时配置limits.conf、systemd服务limitnproc及内核pid_max,缺一不可。

Resource temporarily unavailable 错误在高并发场景下直接调用 start()(如 Java 的 Thread.start()、Python 的 multiprocessing.Process.start() 或 C 的 fork())时频繁出现,根本原因几乎总是 max user processes(即 ulimit -u)被耗尽——而线程和进程共用 PID 空间,一个 Java 应用启 5000 个线程,就已占满默认 4096 或 8192 的限额。
要真正解决,不能只改一处,必须同步打通三层限制:
✅ 查清当前瓶颈在哪
先确认是不是 ulimit -u 真的卡住了:
# 当前 shell 的用户级限制 ulimit -u # 当前服务进程实际生效值(以 nginx 为例) pid=$(pidof nginx); cat /proc/$pid/limits | grep "Max processes" # 全局系统 PID 上限(线程+进程总数天花板) cat /proc/sys/kernel/pid_max # 当前用户所有线程+进程总数(含子线程) ps -eLf | wc -l
若 ps -eLf | wc -l 接近 ulimit -u 值,且 cat /proc/sys/kernel/pid_max 远大于它 → 问题出在用户级限制;
若两者都接近甚至 pid_max 更小 → 必须同时调大 pid_max。
✅ 永久提升用户级 max user processes(ulimit -u)
编辑 /etc/security/limits.conf,添加两行(注意:用空格或制表符分隔,不能用 tab 混淆):
* soft nproc 65535 * hard nproc 65535
⚠️ 关键动作:确保 PAM 加载该配置
检查/etc/pam.d/common-session是否含:session required pam_limits.so如无,手动添加;部分系统还需检查
/etc/pam.d/common-session-noninteractive。
修改后,用户必须重新登录(SSH 重连或 su - $USER),否则不生效。
✅ 为 systemd 服务单独设置 LimitNPROC
limits.conf 对 systemd 启动的服务完全无效。即使你改了全局 limits,systemctl start myapp 仍走 systemd 默认值(常为 512 或 4096)。
-
针对单个服务(推荐):
sudo systemctl edit your-app.service
写入:
[Service] LimitNPROC=65535
-
全局生效(谨慎):
编辑/etc/systemd/system.conf,取消注释并修改:DefaultLimitNPROC=65535
然后执行:
sudo systemctl daemon-reload sudo systemctl restart your-app
验证是否生效:
systemctl show your-app | grep LimitNPROC # 或查进程实际值 cat /proc/$(pidof your-app)/limits | grep "Max processes"
✅ 同步调大内核级 PID 总上限(pid_max)
ulimit -u 再高,若 pid_max 还卡在 32768,就会出现“允许开 65535 个线程,但内核连 PID 都分不出”的情况。
-
临时生效(重启失效):
sudo sysctl -w kernel.pid_max=4194304
-
永久生效:
编辑/etc/sysctl.conf,追加:kernel.pid_max = 4194304
执行:
sudo sysctl -p
✅ 提示:
4194304是 x86_64 架构最大合法值,足够支撑百万级轻量级进程/线程。
✅ 验证与收尾
改完后务必验证三处是否一致:
| 层级 | 检查命令 | 应达目标 |
|---|---|---|
| 用户级 |
ulimit -u(在服务用户下执行) |
≥ 65535 |
| 服务级 | cat /proc/$(pidof your-app)/limits \| grep "Max processes" |
soft/hard 均为 65535 |
| 系统级 | cat /proc/sys/kernel/pid_max |
≥ 4194304 |
若仍有问题,再排查:
- 应用自身是否调用
setrlimit(RLIMIT_NPROC, ...)覆盖了系统设置(如某些 Go runtime 或 Node.js 启动脚本); - 容器环境(Docker/K8s)是否限制了
--ulimit或securityContext; - 是否存在多层封装(如 supervisord、shell wrapper)绕过了 limits 加载。
不复杂但容易忽略











