如果我得到一个初始的“名称或服务未知”(EAI_NONAME),下一次调用getaddrinfo()似乎直接进入dns,而不是首先检查caching(nscd日志显示没有查找尝试,tcpdump显示stream量到DNS服务器)。 如果第一次调用成功获取地址,那么所有getaddrinfo()调用都会按照预期先进入nscd。
我正在编译针对arm linux的glibc-2.13。 在我的rc.d中,nscd是在守护进程之前启动的。 nscd设置为禁止共享caching,并维护主机caching。 我正在使用busybox(0.47)的nscd。 设置nsswitch.conf以便主机检查caching/文件/ dns。 hosts.conf被设置为检查文件/绑定。
我的守护进程调用getaddrinfo()。
我有nscd运行的debugging日志,他们显示客户端开始读取DNS响应closures与“Broken Pipe”错误。
之后,它会显示尝试使用caching的其他守护进程的GAI尝试(所以我知道它不是nscdlocking或任何东西),但获得EAI_NONAME的守护进程永远不会再联系nscd做caching查找。
如果我重新启动守护进程, 如果第一个DNS查询再次超时,我会得到相同的行为。
glibc中是否存在使守护进程的链接无效的内容? 有没有办法重新连接我的守护进程到caching而不重新启动它(类似于通过res_init()强制resolv.conf重新加载?
正如alk在他的评论中提到的 ,重试getaddrinfo()
超过100次应该强制nscd查询。
为了理解为什么,让我们快速浏览一下getaddrinfo()中的执行流程。
getaddrinfo()
调用gaih_inet 。
gaih_inet()
对__nss_not_use_nscd_hosts
执行以下操作:
检查是否超过重试计数NSS_NSCD_RETRY
?
– 只有在满足上述条件的情况下才尝试查询nscd。
在尝试查询nscd时,计数立即重置为零,从而忽略nscd,以调用下一个NSS_NSCD_RETRY
次getaddrinfo()
。
另外__nss_not_use_nscd_hosts
在以下地方由nscd内部修改
nscd / nscd_gethst_r.c行178,189
– 重置为1
。
nscd / nscd_getai.c第89,164行
– 重置为1
。
nss / nsswitch.c,第709行
– 设置为-1
即禁用nscd。
基于上述,可以得出结论getaddrinfo()
不会每次查询nscd。 另外,nscd的内部状态(由__nss_not_use_nscd_hosts
决定)决定getaddrinfo()
最终调用nscd。
为了在100次重试限制的范围内强制执行,可以修改
NSS_NSCD_RETRY
并重建libc以偏离标准行为。 但我不确定这是否会导致任何其他意想不到的回归。
参考:在getaddrinfo()
中引入__nss_not_use_nscd_hosts
逻辑的修补程序。