如果DNS超时,则使用getaddrinfo()仅首次检查nscd缓存

col*_*.mc 11 c linux nss getaddrinfo

如果我得到一个初始的"名称或服务未知"(EAI_NONAME),下一次调用getaddrinfo()似乎直接转到dns而不是先检查缓存(nscd日志显示没有查找尝试,tcpdump显示流量到DNS服务器).如果第一次调用成功获取地址,从那时起,所有getaddrinfo()调用首先转到nscd,如预期的那样.

我正在针对arm linux编译glibc-2.13.在我的rc.d中,nscd在我的守护进程之前启动.nscd设置为禁止共享缓存,并维护主机缓存.我正在使用busybox中的nscd(0.47).设置了nsswitch.conf,以便主机检查cache/files/dns.hosts.conf设置为check files/bind.

我的守护进程正在调用getaddrinfo().

我有运行nscd的调试日志,它们显示客户端开始读取DNS响应关闭时出现"Broken Pipe"错误.

之后它会显示其他守护进程试图使用缓存的GAI尝试(所以我知道它不是nscd锁定或任何东西),但是获得EAI_NONAME的守护进程再也不会联系nscd进行缓存查找.

如果我重新启动守护程序,如果第一个DNS查询再次超时,我会得到相同的行为.

glibc中有什么东西使我的守护进程到缓存的链接无效吗?有没有办法将我的守护进程重新连接到缓存而不重新启动它(类似于通过res_init()强制resolv.conf重新加载)?

The*_*ist 5

正如他在评论中提到的那样,重试getaddrinfo()超过100次应强制进行nscd查询.


要理解为什么,让我们快速浏览一下到执行的流程 的getaddrinfo() .

  1. getaddrinfo()叫gaih_inet.

  2. gaih_inet() 执行以下操作__nss_not_use_nscd_hosts:

    • 检查它是否是正整数?
    • 增加它.
    • 检查它是否超过重试次数NSS_NSCD_RETRY

      • 如果满足上述两个条件,它仅尝试查询nscd.

      • 另外在尝试查询到NSCD,计数立即重置为零
        ,从而忽略nscd的下一个NSS_NSCD_RETRY时间getaddrinfo()被调用.

  3. __nss_not_use_nscd_hosts在以下位置也由nscd在内部修改

基于以上所述,可以得出结论,
getaddrinfo()每次都不查询nscd.

nscd的内部状态(由...确定__nss_not_use_nscd_hosts)
决定是否getaddrinfo()最终调用nscd.

为了真正强制绕过100重试限制,可以修改 NSS_NSCD_RETRY和重建libc以偏离标准行为.但我不确定这是否会导致任何其他无意识的回归.

参考:介绍逻辑的补丁.__nss_not_use_nscd_hostsgetaddrinfo()