﻿# 使用 Java 開發的系統需注意 DNS 快取的問題 (快取一輩子)

之前有替客戶安裝一套 [IBM OmniFind Yahoo! Edition](https://web.archive.org/web/20190802055034/http://omnifind.ibm.yahoo.net/) 在 Linux 環境下，採用的 Java 版本為 1.5.0，最近客戶的主機換機房了導致 IP 變更，搬過去之後發現這個搜尋引擎還能夠查詢，但是卻無法對原本網站進行索引動作，就算我們重新將索引重建，還是無法所以成功，所呈現的訊息都是無法連接至網站，但是本機設定的 DNS 並沒有問題，連線、防火牆也沒問題，即便設定了 /etc/hosts 也還是連不上，這實在太奇怪了，查到最後才發現到原來是 JDK 1.5 以前預設會將 DNS 快取一輩子 (cache forever)，才會導致原本網站怎麼樣都連不上的情況。

以下是我找到問題癥結點的方法：

1.  在 [IBM OmniFind Yahoo! Edition](https://web.archive.org/web/20190802055034/http://omnifind.ibm.yahoo.net/) 的管理介面新增一個網站，讓系統對該網站建立 HTTP 連線
2.  使用 netstat -natp | grep java 指令查詢所有已建立連線
3.  得知原來 [IBM OmniFind Yahoo! Edition](https://web.archive.org/web/20190802055034/http://omnifind.ibm.yahoo.net/) 連接到了該網站的舊 IP 位址
4.  確診為 DNS 問題

接著就開始朝著 DNS 問題打轉：

1.  利用 host 指令測試網址查詢出的 IP 是否正確 ==> 正確無誤
2.  利用 telnet 測試網站 IP 的 Port 80 是否能正常連線 ==> 可以正常連線，所以不是防火牆的問題
3.  設定 /etc/hosts 設定新的網址/IP對應 ==> 系統還是抓到錯誤的 IP 位址

從作業系統這邊都無法解決問題，應該就只剩下**應用系統**的問題了，接著就開始找為什麼 java.exe 無法連線到網址，但所有其他程式都可以連線呢？難道 Java 本身實做了某種快取機制嗎？果不其然，上網搜尋 **java dns cache** 馬上找到答案！

原來是 JDK 從 1.0 ~ 1.5 裡有個 **networkaddress.cache.ttl** 參數 ( 在 java.security 設定檔 )，這裡定義了當 Java 在對網路進行名稱解析時的快取時間，預設為竟然為 **\-1** (cache forever)，而且又這麼剛好這台伺服器超級穩定，主機搬家後重來都沒有重開過，所以這些 DNS 快取資料完全沒有清空，所以還是抓到了錯誤的 IP 位址。… 這又再次證明即便在 Linux 裡 [3R 策略](https://web.archive.org/web/20110527162850/http://en.wikipedia.org:80/wiki/Reboot,_Reformat,_Reinstall)還是奏效的 XD …

新版的 Java 已經修改了 DNS Cache TTL 預設值為 30 秒，不過這個 30 秒從[官方文件](http://download.oracle.com/javase/6/docs/api/java/net/InetAddress.html)上並看不出來，我也是從 [Java's DNS cache behaviour](http://java-monitor.com/forum/showthread.php?t=181) 網頁才知道的，官網文件上的說明比較如下圖示：

[**InetAddress (Java 2 Platform SE 5.0)**](http://download.oracle.com/javase/1.5.0/docs/api/java/net/InetAddress.html) **明確寫出 networkaddress.cache.ttl 預設值為 -1**

![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/ab0e42ad5fb2dfb6a72c-image_820.png)

[**InetAddress (Java Platform SE 6)**](http://download.oracle.com/javase/6/docs/api/java/net/InetAddress.html) **並沒有寫出networkaddress.cache.ttl 的預設值**

![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/f1e801c6ddd46ad223a3-image_821.png)

**相關連結**

-   [Java's DNS cache behaviour](http://java-monitor.com/forum/showthread.php?t=181)
-   [Disable DNS caching - Real's Java How-to](http://www.rgagnon.com/javadetails/java-0445.html)
-   [InetAddress (Java 2 Platform SE 5.0)](http://download.oracle.com/javase/1.5.0/docs/api/java/net/InetAddress.html)
-   [InetAddress (Java Platform SE 6)](http://download.oracle.com/javase/6/docs/api/java/net/InetAddress.html)
