本机那台不做迭代的小组件
应用调用 getaddrinfo 或 gethostbyname 时,真正干活的不是递归服务器,而是操作系统里的存根解析器(Stub Resolver):它只负责按配置顺序决定查 hosts 文件还是把查询转给哪台递归服务器,自己不做从根开始的迭代。因此「解析不对」既可能出在存根层,也可能出在上游递归器。
基本信息
| 职责 | 按 nsswitch 顺序读取 hosts 文件、mDNS、DNS 等后端,把查询转给递归服务器 |
|---|---|
| 常见实现 | glibc resolver、systemd-resolved(监听 127.0.0.53)、Windows DNS Client |
| 配置文件 | Linux 上为 /etc/resolv.conf 与 /etc/nsswitch.conf |
| 超时与重试 | glibc 默认尝试 5 秒超时、2 次重试,可用 options 调整 |
实现对照
| 实现 | 特点 | 排查入口 |
|---|---|---|
| glibc resolver | 直接读 resolv.conf,行为最传统 | resolv.conf 与 nsswitch.conf |
| systemd-resolved | 本机 127.0.0.53 缓存与分流 | resolvectl status 查看真实上游 |
| Windows DNS Client | 自带缓存,行为受组策略影响 | ipconfig /displaydns 查看缓存 |
| 容器内 | resolv.conf 由运行时注入 | 容器内与宿主机解析结果可能不同 |
排查看实际用的 DNS
排查看实际用的 DNS
cat /etc/resolv.conf # 看当前指向的递归服务器
getent hosts example.com # 走 NSS 全链路(含 hosts 文件)
resolvectl status 2>/dev/null | head -20 # systemd-resolved 下看真实上游与分流
strace -f -e trace=connect getent hosts example.com 2>&1 | grep -E '53|address' # 看到底连了谁
# 对比:dig 直接查指定服务器,绕过存根层的 hosts 与缓存
dig @1.1.1.1 example.com A典型使用场景
- 排查「同一个域名应用解析结果和 dig 不一致」:前者走 NSS 全链路,后者直连查询
- 排查容器内解析异常:确认注入的 resolv.conf 与宿主机是否一致
- 确认 hosts 文件是否被某处改写,造成解析被劫持到测试地址
- 调优解析超时:默认 5 秒超时在首次请求失败时会明显拖慢应用启动
systemd-resolved 环境下 /etc/resolv.conf 常指向 127.0.0.53,真实上游要看 resolvectl status 或 /run/systemd/resolve/ 下的配置,直接改 resolv.conf 会被覆盖。
存根层会做缓存(Windows DNS Client 与 systemd-resolved 都有),排查「改了解析不生效」时要先清缓存,而不是反复重试应用。
分层验证比反复猜更快:先用 dig 直连指定服务器确认上游数据正确,再用 getent 验证本机全链路,最后看应用日志确认它真的拿到了这个地址。