我有一個小型 Java 程序,每秒循環調用 InetAddress.getByName("example.com") 。當我使用“strace -f”在 CentOS 6.4 機器上運行它時,我看到 /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 方面的不同行為?
答案1
RedHat glibc 開發人員認為他們軟體中的某些錯誤不是錯誤。這些錯誤之一是更改後重新讀取 resolv.conf。 glibc 認為這是應用程式的責任,因此每個應用程式都需要為此創建自己的邏輯。
因為這絕對是瘋狂的,eglibc 開發人員已經解決了這個問題。因此,在非 elibc 系統上,您的應用程式需要有自己的邏輯來重新初始化 nss_dns,否則需要在 resolv.conf 更改後重新啟動。在 eglibc 系統(Debian 和基於 Debian 的系統)上,您會得到一個 bug 較少的 libc。
在更改 resolv.conf、停用舊的 DNS 伺服器,然後必須重新啟動 1200 多個 mysql 伺服器之後,我們才發現了這一點。不用說,這並不好玩。
答案2
不僅C庫版本不同,而且CentOS使用GNU C庫(glibc
)而Debian使用嵌入式GLIBC(eglibc
),因此名稱查找系統調用的實際實現完全不同。
這可能會解釋這兩個發行版之間不同的系統呼叫行為。
我假設InetAddress.getByName
翻譯成getaddrinfo()
.您可以先閱讀相關 C 程式庫實作和版本中每個系統呼叫的原始程式碼。
確保您從您正在使用的實際套件版本中閱讀原始程式碼。與原始上游版本相比,EL 6.4 中的軟體套件已經完成了 2 年多的改進。我認為 Debian 軟體包也是如此。