1. 程式人生 > >android DNS cache

android DNS cache

當服務端IP變化,大量使用者還是訪問的以前的IP,連線不上伺服器。

我們的客戶端軟體如何通過域名正確訪問伺服器?這裡面主要涉及到DNS快取的問題。

什麼是DNS?

DNS 是域名系統 (Domain Name System) 的縮寫,是因特網的一項核心服務,它作為可以將域名和IP地址相互對映的一個分散式資料庫,能夠使人更方便的訪問網際網路,而不用去記住能夠被機器直接讀取的IP數串。簡單說,DNS就是 域名(我們平時使用的網址,如www.sina.com.cn等)到 ip 地址的 伺服器。

因為計算機訪問對方伺服器時,只能識別對方伺服器的ip地址,所以當我們輸入網址時,就需要先到DNS伺服器查詢對應的IP地址,然後再訪問。

DNS快取

DNS訪問是個比較耗時的操作,所以android會把查詢到的結果快取起來,下次查詢的時候,就可以直接從快取中獲取,而不需要DNS查詢。

DNS解析快取分為兩種:查詢成功的快取,查詢失敗的快取(如查詢域名不存在等) 。

android 系統對DNS快取 有兩個地方,一個是虛擬機器層 , 一個是 框架層 java.net.InetAddress 類內部維護了一個快取。

當通過域名解析IP地址時,通過 java.net.InetAddress類來呼叫相應的方法。它會先檢視自身快取裡有沒有,木有的話會看虛擬機器層有木有快取還木有的話才會到DNS伺服器查詢。

控制DNS快取

有些情況下,我們不能使用DNS快取,如伺服器IP地址變化等。

虛擬機器層預設使用的快取策略是 成功的查詢永久快取(這裡的永久快取是指整個虛擬機器生命週期,虛擬機器重啟,快取就沒有了) , 失敗的查詢只快取10s

我們可以設定虛擬機器的DNS快取時間TTL (time-to-live 生命週期):

  1. Security.setProperty("networkaddress.cache.ttl", String.valueOf(0));  
  2. Security.setProperty("networkaddress.cache.negative.ttl", String.valueOf(0));  

"networkaddress.cache.ttl"
表示查詢成功的快取,"networkaddress.cache.negative.ttl"表示查詢失敗的快取。第二個引數表示快取有效時間,單位是秒。

時間 -1 表示永久快取,0 表示從不快取,其他表示快取具體有效時間。

java.net.InetAddress內部的快取我們沒有辦法控制。4.0以前是永久快取,4.0以後是隻快取2s。也就是說4.0以前通過設定虛擬機器TTL沒有用,因為java.net.InetAddress永久快取了。

下面是android api InetAddress 裡的原話:

DNS caching

In Android 4.0 (Ice Cream Sandwich) and earlier, DNS caching was performed both by InetAddress and by the C library, which meant that DNS TTLs could not be honored correctly.In later releases, caching is done solely by the C library and DNS TTLs are honored.

在控制DNS快取時有兩點需要注意:

    1. 可以根據實際情況來設定networkaddress.cache.ttl屬性的值。一般將這個屬性的值設為-1.但如果訪問的是動態對映的域名(如使用動態域名服務將域名對映成ADSL的動態IP), 就可能產生IP地址變化後,客戶端得到的還是原來的IP地址的情況。

    2. 在設定networkaddress.cache.negative.ttl屬性值時最好不要將它設為-1,否則如果一個域名因為暫時的故障而無法訪問,那麼程式再次訪問這個域名時,即使這個域名恢復正常,程式也無法再訪問這個域名了。除非重新執行程式。


IP變化解決方案

當服務端IP變化,我們的軟體又必須通過域名正確訪問伺服器。

最簡單且通用的解決辦法是,重啟應用程式。

但是我們沒有辦法控制使用者的行為,使用者要是不停止程式的話,就永遠連不上。

解決方案1:在 Application 的 onCreate()裡設定虛擬機器不快取DNS。

假設使用者此時正在使用我們的軟體,此時域名改變IP指向,使用者斷線重連後會獲得正確的IP,成功連線。InetAddress 快取的那2s可以不考慮了。

缺點:4.0下不管用。

解決方案2:在第一次域名解析成功後,將IP地址存到檔案裡。下次連線的時候優先使用儲存的IP地址,只有當IP地址連線不上時,才進行域名解析,解析成功後,再次儲存IP。

方案一加方案二一起解決了大多數使用者的問題。