文件描述符上限是什么
高并发服务的隐性瓶颈常常是文件描述符上限,报错形式是打开文件过多。这个限制分三层:单元级、登录会话级与内核级。修改时必须逐层核对最终生效值,只改其中一层往往看不出效果。
基本信息
| 用途 | 排查与调整文件描述符上限 |
|---|---|
| 三层限制 | 服务单元、登录会话、内核总量 |
| 核对方式 | 查看当前会话限制与目标进程的实际限制 |
| 生效判据 | 以进程实际限制值为准 |
典型使用场景
- 容量评估:按连接数与打开文件数估算所需上限
- 报错定位:出现打开文件过多时确认是进程限制还是内核总量
- 服务调整:给单个服务单独提高上限,不影响整机
- 会话调整:为运维会话或本地脚本临时提高限制
- 内核核对:系统级总量不足时调整内核参数
现状核对
现状核对
ulimit -Sn; ulimit -Hn # 当前会话的软硬限制
cat /proc/$(pgrep -f app.jar | head -1)/limits | grep -i 'open files'
cat /proc/sys/fs/file-max; cat /proc/sys/fs/nr_open调整
调整
# 服务单元(推荐):在 [Service] 段设置 LimitNOFILE=65535
sudo systemctl edit myapp && sudo systemctl restart myapp
# 登录会话:在限额配置文件里设置软硬限制
# 内核级:调整系统总文件数上限
sudo sysctl -w fs.file-max=200000三层对照
| 层次 | 配置位置 | 生效范围 |
|---|---|---|
| 服务单元 | 单元里的资源限制项 | 只影响该服务 |
| 登录会话 | 限额配置文件 | 登录会话及其启动的进程 |
| 内核总量 | 系统参数 | 整机所有进程共享 |
| 进程实际值 | 进程限制文件 | 修改是否生效的最终判据 |
| 容器环境 | 运行时配置与宿主 | 受两者共同约束 |
登录会话的限额配置对 systemd 服务不生效,服务走单元里的资源限制项,两套体系不要混淆。
只调软限不调硬限会被硬限压制,最终要以进程的实际限制值为准。
容器内还受运行时配置与宿主上限的双重约束,调整前先确认卡在哪一层。