У меня есть небольшая программа на 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 () 'd:
$ 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?
Разработчики RedHat glibc не считают некоторые ошибки в своем программном обеспечении ошибками. Одна из этих ошибок - перечитывание файла resolv.conf после изменения. glibc считает, что ответственность за это лежит на приложении, поэтому каждое приложение должно будет создать для этого свою собственную логику.
Поскольку это абсолютно помешательство, разработчики eglibc исправили эту проблему. Таким образом, в системах, отличных от eglibc, ваше приложение должно иметь собственную логику для повторной инициализации nss_dns, иначе его необходимо будет перезапустить после изменения resolv.conf. В системах eglibc (Debian и другие системы на основе Debian) вы получаете libc с меньшими ошибками.
Мы выяснили это на собственном горьком опыте после изменения файла resolv.conf, вывода из эксплуатации старых серверов DNS и последующего перезапуска более 1200 серверов mysql. Излишне говорить, что это не весело.
Различаются не только версии библиотеки C, но и CentOS использует библиотеку GNU C (glibc
), тогда как Debian использует Embedded GLIBC (eglibc
), поэтому реальная реализация системных вызовов поиска имени совершенно другая.
Это, вероятно, объясняет различное поведение системных вызовов между этими двумя дистрибутивами.
Я предполагаю InetAddress.getByName
переводится в getaddrinfo()
. Вы можете начать с чтения источника каждого системного вызова в соответствующей реализации и версиях библиотеки C.
Убедитесь, что вы читаете исходный код из фактических версий пакета, которые используете. Пакеты в EL 6.4 были усовершенствованы более чем за 2 года по сравнению с их исходными исходными версиями. Я предполагаю, что то же самое можно сказать и о пакетах Debian.