Using getaddrinfo() проверяет сначала кеш nscd, если время ожидания DNS

Если я получаю начальное "Имя или услугу неизвестно" (EAI_NONAME), следующий вызов getaddrinfo(), похоже, идет прямо в dns вместо проверки кеша в первую очередь (журналы nscd не показывают попыток поиска, tcpdump показывает трафик на DNS-сервер). Если первый вызов удастся получить адрес, с этого момента все вызовы getaddrinfo() сначала переходят в nscd, как и ожидалось.

Я компилирую против glibc-2.13 для arm linux. В моем rc.d nscd запускается перед моим демоном. nscd настроен на запрещение общих кэшей и поддерживает кеш-хост. Я использую nscd из busybox (0.47). nsswitch.conf установлен так, что хост проверяет кеш/файлы/dns. hosts.conf установлен для проверки файлов /bind.

Мой демон вызывает getaddrinfo().

У меня есть отладочные журналы для запуска nscd, и они показывают, что клиент начал читать ответ DNS закрывается с ошибкой "Broken Pipe".

После этого он покажет попытки GAI от других демонов, пытающихся использовать кеш (поэтому я знаю, что это не nscd заблокировано или что-то еще), но демон, который получил EAI_NONAME, никогда больше не связывается с nscd, чтобы выполнить поиск в кеше.

Если я перезапущу демона, я получаю такое же поведение, если первый запрос DNS снова истечет.

Есть ли что-то в glibc, которое лишает мою демона ссылку на кеш? Есть ли способ повторно подключить мой демон к кэшу, не перезапуская его (аналогично принудительной перезагрузке resolv.conf через res_init())?

Ответ 1

<суб > Как alk упоминает в своем комментарии, повторная попытка getaddrinfo() более 100 раз должна принудительно выполнить запрос nscd.

суб >


Чтобы понять, почему, давайте быстро заглянем в поток выполнения внутри getaddrinfo().

  • getaddrinfo() вызывает gaih_inet.

  • gaih_inet() выполняет следующие операции над __nss_not_use_nscd_hosts:

    • Проверяет, является ли это положительным целым?
    • Увеличивает его.
    • Проверяет, превышает ли он количество попыток NSS_NSCD_RETRY

      - Он пытается запросить nscd ТОЛЬКО, если выполняются оба вышеуказанных условия.

    Также при попытке запроса к nscd счетчик немедленно reset равен нулю, игнорируя nscd для следующего NSS_NSCD_RETRY раз getaddrinfo().

  • Также __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_hosts в getaddrinfo().