Nginx DNS解析慢可通过分析$upstream_connect_time(含DNS+TCP握手)与$request_time比值>20%、$upstream_header_time同步升高、error.log出现“could not be resolved”等日志线索定位,并需确认resolver配置生效、避免proxy_pass使用变量、结合dig/nslookup验证DNS延迟。

直接看 Nginx 日志里的 $upstream_response_time 和 $upstream_connect_time 差值,如果后者明显偏高(比如占总耗时 30% 以上),且 $upstream_header_time 也同步拉长,大概率是 DNS 解析在拖慢转发。
关注 Nginx 访问日志中的关键时间字段
Nginx 默认日志不记录 DNS 解析耗时,但可通过自定义日志格式暴露线索:
- 添加
$upstream_connect_time:表示与 upstream 建立 TCP 连接的时间,包含 DNS 解析 + TCP 握手。若该值持续 >100ms,尤其在后端 IP 稳定、网络正常时,DNS 是首要怀疑对象 - 对比
$upstream_header_time和$upstream_response_time:若两者都高且差值小(即响应体传输快,但首字节慢),说明卡点在连接建立阶段,而非后端处理或网络传输 - 配合
$request_time判断整体影响:当upstream_connect_time / request_time > 0.2时,DNS 开销已成显著瓶颈
检查 resolver 配置是否生效及是否被绕过
DNS 解析问题常因配置“看似存在,实则未用”而被忽略:
- 确认
resolver指令出现在http或location块中,且作用域覆盖了使用域名的proxy_pass;若只写在stream块或遗漏,Nginx 会退回到系统解析器(无缓存、阻塞) - 避免在
proxy_pass中使用变量(如proxy_pass http://$backend;),这会导致每次请求强制走 resolver,无法复用解析结果和 keepalive 连接 - 检查 error.log 是否出现
could not be resolved、resolver timeout或no resolver defined,这些是 DNS 失效的明确信号
结合系统层与上游行为交叉验证
单靠 Nginx 日志不够,需从外围印证 DNS 是否异常:
- 在 Nginx 所在服务器上手动执行
dig origin.example.com @8.8.8.8 +short和nslookup origin.example.com 127.0.0.1,对比响应时间与 TTL,确认所配 resolver 是否低延迟、返回稳定 - 观察后端服务的连接来源:若发现大量新建连接来自不同 IP(而非复用少数连接),说明 keepalive 未生效,根源往往是 DNS 解析未缓存,导致 upstream 名称无法命中已有连接池
- 检查是否有高频
getaddrinfo()系统调用:用strace -p $(pgrep nginx) -e trace=getaddrinfo 2>&1 | grep -c "origin"统计单位时间内解析次数,突增即表明缓存失效或配置缺失
区分 DNS 延迟与其他网络延迟
避免误判的关键是排除干扰项:
- 如果
$upstream_connect_time高,但curl -w "@curl-format.txt" -o /dev/null -s http://origin.example.com在同一台机器上同样慢,则问题出在 DNS 或网络路径,而非 Nginx 配置 - 若仅 Nginx 慢,而 curl 快,说明 Nginx 未复用系统 DNS 缓存(如容器内未挂载
/etc/resolv.conf),或 resolver 配置被 location 层级覆盖丢失 - 启用
resolver_timeout 3s;后仍频繁超时,应检查所选 DNS 服务器本身可用性(如 ping、telnet 端口)、是否被防火墙拦截,或是否启用了 IPv6 导致额外查询延时


















