JVM DNS 緩存配置

域名解析并非一個(gè)簡(jiǎn)單的過程,其解析結(jié)果可能會(huì)被層層緩存,如瀏覽器 DNS 緩存、操作系統(tǒng) DNS 緩存、ISP 的 DNS緩存,容易被忽略的是 JVM 本身也會(huì)對(duì) DNS 進(jìn)行緩存。

JVM 的 DNS 緩存可以通過以下參數(shù)進(jìn)行配置:

  • networkaddress.cache.ttl
  • sun.net.inetaddr.ttl
  1. 如果開啟了 SecurityManager,優(yōu)先從 ${java.home}/jre/lib/security/java.security 中讀取參數(shù) networkaddress.cache.ttl,單位為秒。
  2. 如果未讀取到,則會(huì)讀取啟動(dòng)參數(shù) sun.net.inetaddr.ttl 作為緩存 ttl.
  3. 如果以上參數(shù)均未讀取到,并且未開啟 SecurityManager,則會(huì)使用默認(rèn)值 30s.
  4. 否則使用初始值 -1,表示永久生效。

以上邏輯可以在 InetAddressCachePolicy.class 中體現(xiàn),反編譯后,有如下代碼

static {
        Integer var0 = (Integer)AccessController.doPrivileged(new PrivilegedAction<Integer>() {
            public Integer run() {
                String var1;
                
                // 優(yōu)先讀取 networkaddress.cache.ttl
                try {
                    var1 = Security.getProperty("networkaddress.cache.ttl");
                    if (var1 != null) {
                        return Integer.valueOf(var1);
                    }
                } catch (NumberFormatException var3) {
                    ;
                }
                    
               // 未讀取到,則讀取啟動(dòng)參數(shù) sun.net.inetaddr.ttl
                try {
                    var1 = System.getProperty("sun.net.inetaddr.ttl");
                    if (var1 != null) {
                        return Integer.decode(var1);
                    }
                } catch (NumberFormatException var2) {
                    ;
                }

                return null;
            }
        });
        if (var0 != null) {
            cachePolicy = var0.intValue();
            if (cachePolicy < 0) {
                cachePolicy = -1;
            }

            propertySet = true;
        } else if (System.getSecurityManager() == null) {
            // 如果未啟用 SecurityManager,使用默認(rèn)值 30
            cachePolicy = 30;
        }

其中 cachePolicy 初始值為 -1,表示緩存永不失效。

我們通過以下代碼對(duì) DNS 緩存參數(shù)進(jìn)行測(cè)試:

public class HostProcessor implements Runnable {

    private int count = 1;

    /**
     * 每秒解析1次 www.baidu.com 的 IP
     */
    @Override
    public void run() {
        while (true) {
            System.out.println(count);
            printIp("www.baidu.com");

            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            count = count + 1;
            System.out.print("\r\n");
        }
    }

    /**
     * 解析并打印 IP
     */
    private void printIp(String host) {
        InetAddress address = null;
        try {
            address = Inet4Address.getByName(host);
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }

        if (address == null) {
            return;
        }

        System.out.println(address.getHostAddress());
        System.out.println(address.getHostName());
    }

    public static void main(String[] args) {
        Thread thread = new Thread(new HostProcessor());
        thread.start();
    }
}

networkaddress.cache.ttl 參數(shù)測(cè)試
首先修改 java.security 中的 networkaddress.cache.ttl 配置,改為以下值:

networkaddress.cache.ttl=15

啟動(dòng)程序,開始打印域名對(duì)應(yīng) IP 后,立刻修改 /etc/hosts,將 www.baidu.com 指向到陌生 IP:

47.95.164.112   www.baidu.com

觀察控制臺(tái)輸出,有如下結(jié)果:


image

在 15 秒后,對(duì) host 映射的修改才反應(yīng)出來

sun.net.inetaddr.ttl 參數(shù)測(cè)試
注釋掉 java.security 中的 networkaddress.cache.ttl 配置,如下:

#networkaddress.cache.ttl=15

添加程序啟動(dòng)參數(shù):

-Dsun.net.inetaddr.ttl=10

同樣啟動(dòng)程序后,將原先 host 文件的修改回退,觀察到如下輸出:


image

在 10 秒后,對(duì) host 映射的修改才反應(yīng)出來

除了解析成功的結(jié)果,JVM 也會(huì)緩存解析失敗的結(jié)果,可以通過下列參數(shù)配置:

  • networkaddress.cache.negative.ttl
  • sun.net.inetaddr.negative.ttl
    這里不展開介紹
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容