首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 網路程式設計精通指南(4):DNS 緩存機制 — 配置、驗證與負緩存陷阱

     編輯:Java 相關知識

Java 內建 DNS 緩存機制,緩存正向解析結果 (域名→IP) 與負向解析結果 (域名不存在)。本文詳解緩存配置參數、代碼驗證正/負緩存行為、動態域名場景風險及最佳配置策略。

兩大緩存配置屬性

屬性名作用默認值單位配置方式
networkaddress.cache.ttl正向解析緩存生存時間-1 (永不過期)秒Security.setProperty / java.security 文件
networkaddress.cache.negative.ttl負向解析緩存生存時間 (域名不存在)10秒Security.setProperty / java.security 文件

配置方法

1. 運行時代碼設置 (即時生效,僅當前 JVM)

// 正向緩存 30 秒
java.security.Security.setProperty("networkaddress.cache.ttl", "30");
// 負向緩存 5 秒
java.security.Security.setProperty("networkaddress.cache.negative.ttl", "5");

2. 全局配置文件 (永久生效,所有 JVM)

文件位置:$JAVA_HOME/jre/lib/security/java.security (JDK 8) 或 $JAVA_HOME/conf/security/java.security (JDK 9+)。

networkaddress.cache.ttl=30
networkaddress.cache.negative.ttl=5

特殊值含義

  • ttl = -1:永久緩存,JVM 重啟前不釋放。
  • ttl = 0:禁用緩存,每次解析都查 DNS。
  • negative.ttl = 0:禁用負緩存,每次都查 DNS 確認不存在。

代碼驗證:正向緩存命中 vs 過期

public class DnsCacheDemo {
    public static void main(String[] args) throws Exception {
        if (args.length < 2) return; // args[0]=host, args[1]=ttl秒
        Security.setProperty("networkaddress.cache.ttl", args[1]);

        String host = args[0];
        // 第一次解析
        long t1 = System.currentTimeMillis();
        InetAddress[] addrs1 = InetAddress.getAllByName(host);
        System.out.println("第1次: " + (System.currentTimeMillis()-t1) + "ms");
        for (InetAddress a : addrs1) System.out.println("  " + a);

        System.out.print("按任意鍵繼續... "); System.in.read();

        // 第二次解析
        long t2 = System.currentTimeMillis();
        InetAddress[] addrs2 = InetAddress.getAllByName(host);
        System.out.println("第2次: " + (System.currentTimeMillis()-t2) + "ms");
        for (InetAddress a : addrs2) System.out.println("  " + a);
    }
}

測試場景

$ java DnsCacheDemo www.126.com 5
第1次: 344ms
  www.126.com/202.108.9.77
按任意鍵繼續... (5秒內按鍵)
第2次: 0ms          ← 緩存命中
  www.126.com/202.108.9.77

$ java DnsCacheDemo www.126.com 5
第1次: 344ms
按任意鍵繼續... (5秒後按鍵)
第2次: 484ms        ← 緩存過期,重新查 DNS
  www.126.com/202.108.9.77

負緩存驗證:域名不存在的快速失敗

public class NegativeCacheDemo {
    public static void main(String[] args) throws Exception {
        Security.setProperty("networkaddress.cache.negative.ttl", "5"); // 5秒負緩存

        long t1 = System.currentTimeMillis();
        try { InetAddress.getByName("www.ppp123.com"); } // 不存在域名
        catch (UnknownHostException e) {
            System.out.println("第1次失敗: " + (System.currentTimeMillis()-t1) + "ms");
        }

        // Thread.sleep(6000); // 取消註釋測試過期後

        long t2 = System.currentTimeMillis();
        try { InetAddress.getByName("www.ppp123.com"); }
        catch (UnknownHostException e) {
            System.out.println("第2次失敗: " + (System.currentTimeMillis()-t2) + "ms");
        }
    }
}

輸出

第1次失敗: 4688ms  ← 真實 DNS 查詢超時
第2次失敗: 0ms     ← 負緩存命中,即時拋異常

// 若睡眠 6 秒後:
第1次失敗: 4688ms
第2次失敗: 4420ms  ← 負緩存過期,再次真實查詢

兩大風險場景與應對

場景風險建議配置
動態域名 (DDNS、ADSL 映射)IP 變更後客戶端仍用舊 IP,連接失敗ttl = 30~300 秒,平衡性能與時效性
臨時故障導致域名解析失敗負緩存導致故障恢復後仍報錯,需重啟 JVMnegative.ttl = 10~60 秒,**嚴禁設 -1**

最佳實踐總結

  1. 生產環境 正向緩存設 60~300 秒,避免頻繁 DNS 查詢壓力。
  2. 負緩存設 10~60 秒,防止臨時故障長期污染,且不設 -1。
  3. 動態域名場景 (DDNS、服務發現) **縮短正向 TTL** 或使用專用服務發現組件 (Consul, Nacos, Eureka) 繞過 JVM DNS 緩存。
  4. 容器/K8s 環境建議 ttl=30,配合 CoreDNS 自動更新。
  5. 監控 DNS 解析延遲與失敗率,異常時可運行時動態調整 Security.setProperty。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved