公司內網環境中許多調用資源(數據庫、web接口等)都是經過內網DNS服務來進行域名-IP的映射。java
但常常出現DNS映射修改完畢後,應用中鏈接的資源遲遲沒有變動。linux
之前一直籠統的認爲是linux的dns緩存致使,今天作了一次完整的分析,結果以下:web
一、Linux系統的本地DNS的緩存redis
CentOS系統自己並不包含DNS的緩存機制,除非安裝並啓動了nscd服務(name server cache daemon)。數據庫
nscd服務啓動後會默認爲本地的全部dns解析作一層緩存,過時時間默認爲3600秒,重啓應用程序也不會重置nscd的緩存,除非用/etc/init.d/nscd reload,強制刷新nscd緩存。緩存
開啓nscd服務能夠大大下降應用程序請求DNS服務的頻率,同時必定程度上能夠對DNS服務的故障有必定容錯。但缺點很是明顯,DNS服務的映射改變沒法實時的被應用程序感知,每次修改映射後都必須在全部客戶端機器reload nscd。服務器
以上結論經過DNS服務日誌獲得驗證。網絡
二、JVM虛擬機的本地DNS緩存測試
實如今java.net.InetAddress的一個簡單的DNS緩存機制,之前被誤認爲是Linux的DNS緩存,jdk6/7中默認爲緩存30秒。.net
緩存範圍爲JVM虛擬機進程,也就是說同一個JVM進程中,30秒內只會爲一個域名請求DNS服務器一次,能夠大大下降應用程序對DNS解析的網絡損耗和對DNS服務產生的壓力。
以上結論經過JAVA測試程序和DNS服務日誌獲得驗證。
三、長鏈接的處理(數據庫連接、redis鏈接、zookeeper、activeMQ鏈接等)
根據一、2兩點結論,當內網DNS服務某一個域名映射修改後,應用程序最多在30秒內就會響應該變化。但實際確不是如此,緣由就是不少資源是「長鏈接」方式。
好比數據庫鏈接池這種就是典型的長鏈接,爲了保證鏈接池效率,咱們也不能把單個鏈接的有效期設的過短。這就致使了這類長鏈接沒法快速響應DNS服務器的映射改變。
解決辦法只有一個:DNS服務器的映射變動後,須要對應用程序作重啓,以便讓長鏈接按照新的DNS映射來進行創建。
以上結論經過JAVA測試程序和DNS服務日誌獲得驗證。
饒了一圈,最後仍是回到原點:
爲了保證應用程序裏的這些長鏈接資源可以及時響應DNS映射的改變,目前仍是得靠重啓應用來解決。