Netty Client使用域名重連的問題

DNS解析過程

  1. 在瀏覽器中輸入www.baidu.com域名,操做系統會先檢查本身本地的hosts文件是否有這個網址映射關係,若是有,就先調用這個IP地址映射,完成域名解析。
  2. 若是hosts裏沒有這個域名的映射,則查找本地DNS解析器緩存,是否有這個網址映射關係,若是有,直接返回,完成域名解析。
  3. 若是hosts與本地DNS解析器緩存都沒有相應的網址映射關係,首先會找TCP/IP參數中設置的首選DNS服務器,在此咱們叫它本地DNS服務器,此服務器收到查詢時,若是要查詢的域名,包含在本地配置區域資源中,則返回解析結果給客戶機,完成域名解析,此解析具備權威性。
  4. 若是要查詢的域名,不禁本地DNS服務器區域解析,但該DNS服務器已緩存了此網址映射關係,則調用這個IP地址映射,完成域名解析,此解析不具備權威性。
  5. 若是本地DNS服務器本地區域文件與緩存解析都失效,則根據本地DNS服務器的設置(沒有設置轉發器)進行查詢,若是未用轉發模式,本地DNS就把請求發至13臺根DNS,根DNS服務器收到請求後會判斷這個域名(.com)是誰來受權管理,並會返回一個負責該頂級域名服務器的一個IP。本地DNS服務器收到IP信息後,將會聯繫負責 .com域的這臺服務器。這臺負責 .com域的服務器收到請求後,若是本身沒法解析,它就會找一個管理 .com域的下一級DNS服務器地址(baidu.com)給本地DNS服務器。當本地DNS服務器收到這個地址後,就會找baidu.com域服務器,重複上面的動做進行查詢,直至找到www.baidu.com主機。
  6. 若是用的是轉發模式(設置轉發器),此DNS服務器就會把請求轉發至上一級ISP DNS服務器,由上一級服務器進行解析,上一級服務器若是不能解析,或找根DNS或把轉請求轉至上上級,以此循環。無論是本地DNS服務器用是是轉發,仍是根提示,最後都是把結果返回給本地DNS服務器,由此DNS服務器再返回給客戶機。 注:從客戶端到本地DNS服務器是屬於遞歸查詢,而DNS服務器之間就是迭代查詢。

Linux對DNS的支持

Linux操做系統自己沒有對DNS緩存的支持(做爲客戶端時),若是爲了提高性能,可使用nscd提供DNS緩存的支持。php

Java對DNS緩存的支持

Java語言對DNS緩存的支持

java.net.InetAddress使用DNSNameService正向經過主機名得到IP地址,或者經過IP地址反向解析獲得主機名。 java.net.InetAddress提供了DNS解析成功的域名記錄的緩存,解析失敗的域名記錄的緩存。 解析成功的域名記錄的緩存的緩存有效期是永久的,解析失敗的域名記錄的緩存的有效期是10s。 這樣作的目的是提高性能,以及防止DNS欺騙攻擊。 當編程時,須要特別注意,一旦鏈接斷開,須要注意從新 new 一個 InetAddress 對象,並進行重連。html

清除InetAddress緩存的方法java

public static void clearCache() throws NoSuchFieldException, IllegalAccessException {  
    //修改緩存數據開始  
    Class clazz = java.net.InetAddress.class;  
    final Field cacheField = clazz.getDeclaredField("addressCache");  
    cacheField.setAccessible(true);  
    final Object obj = cacheField.get(clazz);  
    Class cacheClazz = obj.getClass();  
    final Field cachePolicyField = cacheClazz.getDeclaredField("type");  
    final Field cacheMapField = cacheClazz.getDeclaredField("cache");  
    cachePolicyField.setAccessible(true);  
    cacheMapField.setAccessible(true);  
    final Map cacheMap = (Map)cacheMapField.get(obj);  
    System.out.println(cacheMap);  
    cacheMap.remove("www.baidu.com");  //清除指定的域名緩存
}

JVM對DNS緩存的支持

JVM緩存了DNS的解析結果,一樣提供兩種記錄(解析成功和解析失敗)的緩存,可是相關的信息有JVM維護和管理。 不過sun提供了兩種方式對JVM的DNS成功和失敗緩存的有效期進行設置。編程

java.security.Security方式

  • 修改jvm的配置java.security

jre/lib/security/java.security 下的 networkaddress.cache.ttl 解析成功的緩存有效期,默認永久有效。bootstrap

jre/lib/security/java.security 下的 networkaddress.cache.negative.ttl 解析失敗的緩存有效期,默認10秒。瀏覽器

  • java代碼設置

java.security.Security.setProperty("networkaddress.cache.ttl", "3"); java.security.Security.setProperty("networkaddress.cache.negative.ttl", "1");緩存

任意負值:緩存永久有效
0:不作緩存
正值:緩存多久(單位爲秒)

java.lang.System方式

  • java代碼設置

System.setProperty("sun.net.inetaddr.ttl", "3"); System.setProperty("sun.net.inetaddr.negative.ttl", "1");服務器

  • 添加啓動參數

-Dsun.net.inetaddr.ttl=3 -Dsun.net.inetaddr.negative.ttl=1jvm

Netty對DNS緩存的支持

在Netty4.0版本以前是沒有對DNS的支持的,在4.0以後加入了DNS的。socket

可是在使用netty時,須要對使用域名進行鏈接的應用而言,須要特別注意對重連的考慮。 netty client使用InetSocketAddress指定服務端地址,而InetSocketAddress使用InetAddress進行域名的解析和緩存解析結果。這裏要特別消息,InetAddress使用DNSNameService進行解析的過程,受networkAddress.cache.ttl影響,可是解析後的結果InetSocketAddress,是不會再被刷新了,除非你本身去刷新。而且nio connect的時候使用的是InetSokcetAddress解析後的ip創建鏈接。

nio connect

所以當使用域名的狀況下,當IP進行了切換致使鏈接斷開時,須要從新設置bootstrap的remoteAddress屬性,不然沒法進行IP的切換。

參考資料

DNS解析過程詳解

Linux DNS緩存

IP地址和socket地址

java dns cache

java dns緩存問題

IBM java dns緩存

amazon java dns緩存分析

相關文章
相關標籤/搜索