worker_rlimit_nofile 通过扩大单 worker 进程文件句柄上限,缓解动态域名解析引发的 DNS socket 和连接句柄堆积,避免 Too many open files 导致的解析失败或 502 错误。

worker_rlimit_nofile 本身不直接解决“域名解析”带来的句柄消耗,但它能缓解因高频、动态域名解析行为(如 proxy_pass http://$host、resolver 配合变量后端)引发的 DNS socket 和连接句柄堆积,从而避免 Too many open files 导致的解析失败或 502 错误。关键在于:Nginx 在启用动态 DNS 解析时,每次 resolver 查询会创建临时 UDP socket,每个活跃 upstream 连接也占用 fd,海量域名 + 高并发下极易打满限制。
为什么海量域名解析会吃光文件句柄?
-
resolver指令启用后,Nginx 不再依赖系统 libc 的阻塞式解析,而是用非阻塞 UDP socket 自行发 DNS 查询; - 每次变量型
proxy_pass http://$upstream_host或fastcgi_pass $fastcgi_backend触发解析,都可能新建一个或多个临时 socket; - 若 DNS 响应慢、超时重试多、或缓存未命中率高(
valid设置过短),socket 积压加剧; - 同时,每个活跃 HTTP 连接、日志文件、缓存文件句柄也共用同一 fd 池 ——
worker_rlimit_nofile就是这个池子的上限。
正确配置 worker_rlimit_nofile 应对域名解析场景
-
必须写在
nginx.conf最外层(main 上下文),在 events 块之前、http 块之外:worker_rlimit_nofile 131072; events { use epoll; worker_connections 90000; } -
数值建议设为 131072(128K)或 262144(256K),前提是系统允许:
- 它不能超过 Nginx 运行用户(如
nginx或www-data)的hard nofile; - 推荐设为硬限制的 90%,例如
ulimit -Hn输出145636,则配131072更稳妥。
- 它不能超过 Nginx 运行用户(如
-
worker_connections要同步下调,留足余量给 DNS socket、日志、SSL 会话等:- 公式:
worker_connections ≤ worker_rlimit_nofile × 0.7 - 示例:
worker_rlimit_nofile 131072→worker_connections不超过90000
- 公式:
必须同步调整的系统与服务层限制
只改 Nginx 配置无效,三处必须对齐:
-
systemd 服务限制(推荐,主流发行版默认)
创建/etc/systemd/system/nginx.service.d/override.conf:[Service] LimitNOFILE=131072
然后执行:
systemctl daemon-reload && systemctl restart nginx
-
系统级 ulimit(补充或兼容非 systemd 场景)
编辑/etc/security/limits.conf,添加:nginx soft nofile 131072 nginx hard nofile 131072
确保
/etc/pam.d/common-session包含:session required pam_limits.so
-
验证是否真正生效
查看任一 worker 进程的实际限制:cat /proc/$(pgrep -f "nginx: worker" | head -n1)/limits | grep "Max open files"
输出中
Soft Limit应与你配置的worker_rlimit_nofile一致。
配合域名解析场景的关键调优项
-
合理设置
resolver缓存时效,减少重复查询:http { resolver 8.8.8.8 114.114.114.114 valid=30s; resolver_timeout 5s; }-
valid=30s表示 DNS 结果缓存 30 秒,避免每秒都查; -
resolver_timeout控制单次查询等待上限,防卡死。
-
禁用无意义的
resolver重试逻辑
不要在location中反复写resolver;统一在http或server块顶层配置一次即可。-
避免在
if或低效上下文中动态拼接$host
如proxy_pass http://$host易触发频繁解析,优先用map预定义可信后端:map $host $backend { hostnames; example.com backend-v1; api.example.com backend-v2; default backend-default; } proxy_pass http://$backend; -
确认内核
fs.file-max足够
海量域名解析 + 高并发时,系统总 fd 需求 =worker_processes × worker_rlimit_nofile + 其他进程
建议:sysctl -w fs.file-max=4194304 # ≥ 4M echo 'fs.file-max = 4194304' >> /etc/sysctl.conf











