매초마다 InetAddress.getByName("example.com") 호출을 반복하는 작은 Java 프로그램이 있습니다. 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
두 시스템 모두 실행 중인 이름 캐싱 데몬이 없습니다.
Java 차이점을 배제하기 위해 두 시스템 모두에서 동일한 버전의 Oracle HotSot Java JVM을 사용했습니다.
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은 Embedded GLIBC( eglibc
)를 사용하므로 이름 조회 시스템 호출의 실제 구현이 완전히 다릅니다.
이는 아마도 이 두 배포판 간의 서로 다른 시스템 호출 동작을 설명할 것입니다.
InetAddress.getByName
로 번역된다고 가정합니다 getaddrinfo()
. 관련 C 라이브러리 구현 및 버전에서 각 syscall의 소스를 읽는 것부터 시작할 수 있습니다.
사용 중인 실제 패키지 버전의 소스를 읽어보세요. EL 6.4의 패키지는 원래 업스트림 버전에 비해 2년 넘게 개선되었습니다. 데비안 패키지도 마찬가지라고 생각합니다.