一、DNS簡(jiǎn)介
? ? 日常上網(wǎng)大家一般都是使用域名滋捶,比如www.baidu.com逆日。當(dāng)你在瀏覽器輸入了www.baidu.com的時(shí)候,就是用到了DNS技術(shù)奠滑。將域名解析為ip地址丹皱。
? ? ?域名是分等級(jí)的妒穴,分為:根域名、頂級(jí)域名种呐、次級(jí)域名宰翅、主機(jī)名。一般格式如下:主機(jī)名.次級(jí)域名.頂級(jí)域名.根域名爽室。
二汁讼、JAVA中使用DNS
有兩種方式:
使用InetAddress的getByName方法
InetAddress inetAddress = InetAddress.getByName("unKnownHost");
Socket ss = newSocket(inetAddress,123);
直接使用Socket封裝好的(不推薦):
Sockets = newSocket("unKnownHost",123);
三、JAVA對(duì)DNS的緩存
java獲取host對(duì)應(yīng)ip的過程如下(只關(guān)注查找ip的過程):
1.通過host先去本地緩存中獲取阔墩,本地緩存分為addressCache(有效緩存)和negativeCache(無效緩存)
? ? 1.1如果addressCache中存在嘿架,則返回緩存的結(jié)果
? ? 1.2如果negativeCache中存在,則返回unknown_array啸箫,外層會(huì)拋出UnKnownHostException
? ? ?1.3如果兩個(gè)緩存均不存在耸彪,則返回null
2.如果緩存返回的為null,則去nameService中去查詢忘苛。這里有一個(gè)小優(yōu)化蝉娜,jdk維護(hù)了一個(gè)lookupTable對(duì)象,存放正在查詢的域名扎唾。
? ? 2.1 如果lookupTable中存在host召川,則說明有另外一個(gè)線程在查詢,當(dāng)前線程等待另外一個(gè)線程完成胸遇。
? ? 2.2 如果lookupTable中不存在host荧呐,則將該host放入lookupTable中,并去nameService中查詢纸镊,查詢nameService后倍阐,無論結(jié)果,均會(huì)喚醒所有在等待的線程逗威。
? ? 2.3這樣做的好處峰搪,防止同樣的host并發(fā)去查詢dns,這也是一種防止緩存雪崩的技術(shù)凯旭。
四罢艾、緩存策略
那么有讀者就要問了,因?yàn)閕p有可能改變尽纽,那么緩存的時(shí)間是怎么控制的。那就看另外一個(gè)類:InetAddressCachePolicy
有四個(gè)參數(shù)可以控制緩存時(shí)間(-1 永久有效童漩;0 不緩存弄贿;其余正值 緩存時(shí)間):
networkaddress.cache.ttl ? ? 有效緩存時(shí)間(優(yōu)先級(jí)高)
sun.net.inetaddr.ttl ? 有效緩存時(shí)間(優(yōu)先級(jí)低)
networkaddress.cache.negative.ttl 無效緩存時(shí)間(優(yōu)先級(jí)高)
sun.net.inetaddr.negative.ttl ?無效緩存時(shí)間(優(yōu)先級(jí)低)
這四個(gè)參數(shù),均可以通過啟動(dòng)java程序中矫膨,增加-D參數(shù)進(jìn)行傳入
五差凹、坑
還記得前邊說的不建議直接使用socket的String類型host構(gòu)造函數(shù)嗎期奔?我認(rèn)為哪個(gè)是坑。代碼中可以看到危尿,異常被吞掉了呐萌,雖然對(duì)外的結(jié)果都是UnknownHostException,但是缺少了第一手的堆棧信息谊娇,很難區(qū)分是由于緩存的無效地址還是因?yàn)椴檎沂 ?/p>