排查nginx因dns慢查询导致性能卡顿,核心是确认连接建立阶段是否被dns拖住:通过$upstream_connect_time>100ms、$upstream_header_time同步升高、$upstream_connect_time/$request_time>20%定位耗时异常,结合error.log中“could not be resolved”等日志、resolver配置生效性验证及dig/nslookup交叉验证。

排查 Nginx 因 DNS 慢查询导致的性能卡顿,核心是确认“连接建立阶段是否被 DNS 拖住”,而不是泛泛检查响应慢。关键不在于总耗时高,而在于耗时结构异常——DNS 解析悄悄吃掉了大量时间,但日志里不直接写“DNS 耗时”。
看日志里的耗时分布是否失衡
在 Nginx 访问日志中启用自定义格式,重点观察三个字段:
- $upstream_connect_time:包含 DNS 解析 + TCP 握手。若持续 >100ms(尤其后端 IP 稳定、网络无抖动时),DNS 是首要怀疑对象
- $upstream_header_time:从连接建立到收到响应头的时间。若它和 $upstream_connect_time 同步升高、且两者差值很小(说明首字节就慢),说明卡点在连接前,而非后端处理
- $request_time / $upstream_connect_time 比值:若 $upstream_connect_time 占 $request_time 超过 20%,DNS 开销已成显著瓶颈
查 error.log 是否暴露解析失败线索
错误日志是 DNS 问题最直接的证据源:
- 出现 “could not be resolved” → 域名根本无法解析
- 出现 “resolver timeout” 或 “no resolver defined” → 配置缺失或超时太严
- 出现 “resolving 'xxx.example.com'” 且后续无成功记录 → 解析长期挂起,可能卡在 UDP 重传或 IPv6 协商
验证 resolver 配置是否真正生效
很多问题是“看着配了,其实没用”:
- 确认 resolver 写在 http 块顶层(不是 stream 或 server 块内),且作用域覆盖了使用域名的 proxy_pass
- 避免 proxy_pass 直接写域名(如
proxy_pass http://api.example.com;)→ 这会触发启动时静态解析,绕过 resolver 和 timeout - 必须用 变量方式(
set $upstream "api.example.com"; proxy_pass http://$upstream;)或 upstream resolve(Nginx ≥ 1.19.0)才能触发动态解析 - 检查是否配置了 valid=xxs(如
valid=30s)→ 没设 valid,DNS 结果不缓存,每次请求都查,放大延迟
交叉验证系统层与上游行为
单看 Nginx 日志不够,需从外围印证:
- 在 Nginx 服务器上执行:
dig api.example.com @8.8.8.8 +short和nslookup api.example.com 127.0.0.1,对比响应时间与 TTL,确认所配 resolver 是否低延迟、返回稳定 - 观察后端连接来源:若发现大量新建连接来自不同源 IP(而非复用少数连接),说明 keepalive 失效 → 根源往往是 DNS 未缓存,导致 upstream 名称无法命中已有连接池
- 用
strace -p $(pgrep nginx) -e trace=getaddrinfo 2>&1 | grep -c "api.example.com"统计单位时间内解析次数,突增即表明缓存失效或配置缺失











