一、DNS簡介
? ? 日常上網大家一般都是使用域名,比如www.baidu.com。當你在瀏覽器輸入了www.baidu.com的時候,就是用到了DNS技術。將域名解析為ip地址。
? ? ?域名是分等級的,分為:根域名、頂級域名、次級域名、主機名。一般格式如下:主機名.次級域名.頂級域名.根域名。
二、JAVA中使用DNS
有兩種方式:
使用InetAddress的getByName方法
InetAddress inetAddress = InetAddress.getByName("unKnownHost");
Socket ss = newSocket(inetAddress,123);
直接使用Socket封裝好的(不推薦):
Sockets = newSocket("unKnownHost",123);
三、JAVA對DNS的緩存
java獲取host對應ip的過程如下(只關注查找ip的過程):
1.通過host先去本地緩存中獲取,本地緩存分為addressCache(有效緩存)和negativeCache(無效緩存)
? ? 1.1如果addressCache中存在,則返回緩存的結果
? ? 1.2如果negativeCache中存在,則返回unknown_array,外層會拋出UnKnownHostException
? ? ?1.3如果兩個緩存均不存在,則返回null
2.如果緩存返回的為null,則去nameService中去查詢。這里有一個小優化,jdk維護了一個lookupTable對象,存放正在查詢的域名。
? ? 2.1 如果lookupTable中存在host,則說明有另外一個線程在查詢,當前線程等待另外一個線程完成。
? ? 2.2 如果lookupTable中不存在host,則將該host放入lookupTable中,并去nameService中查詢,查詢nameService后,無論結果,均會喚醒所有在等待的線程。
? ? 2.3這樣做的好處,防止同樣的host并發去查詢dns,這也是一種防止緩存雪崩的技術。
四、緩存策略
那么有讀者就要問了,因為ip有可能改變,那么緩存的時間是怎么控制的。那就看另外一個類:InetAddressCachePolicy
有四個參數可以控制緩存時間(-1 永久有效;0 不緩存;其余正值 緩存時間):
networkaddress.cache.ttl ? ? 有效緩存時間(優先級高)
sun.net.inetaddr.ttl ? 有效緩存時間(優先級低)
networkaddress.cache.negative.ttl 無效緩存時間(優先級高)
sun.net.inetaddr.negative.ttl ?無效緩存時間(優先級低)
這四個參數,均可以通過啟動java程序中,增加-D參數進行傳入
五、坑
還記得前邊說的不建議直接使用socket的String類型host構造函數嗎?我認為哪個是坑。代碼中可以看到,異常被吞掉了,雖然對外的結果都是UnknownHostException,但是缺少了第一手的堆棧信息,很難區分是由于緩存的無效地址還是因為查找失敗。