У меня есть небольшая программа Java, которая циклически вызывает InetAddress.getByName("example.com") каждую секунду. Когда я запускаю ее на CentOS 6.4 с помощью 'strace -f', я вижу, что /etc/resolv.conf открывается и читается один раз:
$ grep /etc/resolv.conf strace.out
[pid 24810] open("/etc/resolv.conf", O_RDONLY) = 6
При запуске на Debian 7 я вижу, что /etc/resolv.conf многократно открывается или подвергается stat():
$ grep /etc/resolv.conf strace.out
[pid 41821] open("/etc/resolv.conf", O_RDONLY) = 10
[pid 41821] stat("/etc/resolv.conf", {st_mode=S_IFREG|0644, st_size=92, ...}) = 0
[pid 41821] open("/etc/resolv.conf", O_RDONLY) = 10
[pid 41821] stat("/etc/resolv.conf", {st_mode=S_IFREG|0644, st_size=92, ...}) = 0
[pid 41821] stat("/etc/resolv.conf", {st_mode=S_IFREG|0644, st_size=92, ...}) = 0
В обеих системах файл /etc/nsswitch.conf настроен следующим образом:
хосты: файлы dns
Ни в одной из систем не запущен демон кэширования имен.
Я использовал одну и ту же версию Oracle HotSot Java JVM на обеих машинах, чтобы исключить любые различия в Java.
На компьютере CentOS 6.4 установлена glibc 2.12. На компьютере Debian 7 установлена glibc 2.13.
Чем объясняется различное поведение двух операционных систем при открытии и чтении /etc/resolv.conf?
решение1
Разработчики RedHat glibc считают некоторые ошибки в своем программном обеспечении не ошибками. Одна из таких ошибок — повторное чтение resolv.conf после изменения. glibc считает, что это ответственность приложения, поэтому каждому приложению нужно будет создать свою собственную логику для этого.
Поскольку это полный бред, разработчики eglibc исправили эту проблему. Так что в системах, отличных от eglibc, вашему приложению понадобится собственная логика для повторной инициализации nss_dns, или его придется перезапускать после изменения resolv.conf. В системах eglibc (Debian и все, что основано на Debian) вы получаете менее глючный libc.
Мы обнаружили это трудным путем после изменения resolv.conf, вывода из эксплуатации старых DNS-серверов и последующей перезагрузки более 1200 серверов mysql. Излишне говорить, что это не весело.
решение2
Различаются не только версии библиотеки C, но и CentOS использует библиотеку GNU C ( glibc
), тогда как Debian использует встроенную GLIBC ( eglibc
), поэтому фактическая реализация системных вызовов поиска имен совершенно разная.
Это, вероятно, объясняет различное поведение системных вызовов в этих двух дистрибутивах.
Я предполагаю, InetAddress.getByName
что преобразуется в getaddrinfo()
. Вы можете начать с чтения исходного кода каждого системного вызова в соответствующей реализации и версиях библиотеки C.
Убедитесь, что вы читаете исходный код фактических версий пакетов, которые вы используете. Пакеты в EL 6.4 подверглись более чем 2-летним улучшениям по сравнению с их первоначальными версиями. Я предполагаю, что то же самое относится и к пакетам Debian.