JVM DNS Cache

Java应用UnknownHostException排查指南:从DNS原理到架构优化 DNS解析是网络通信的基础环节,它将人类可读的域名转换为机器可识别的IP地址,是分布式系统和微服务架构中服务发现与调用的关键技术支撑。其工作原理涉及本地缓存、操作系统查询及远程DNS服务器协作,确保网络请求能够准确路由。在Java应用中,DNS解析的稳定性直接影响服务可用性,不当的缓存策略或配置错误可能导致 `UnknownHostException`,进而引发服务调用失败。本文聚焦于 `UnknownHostException` 这一典型故障,结合 **JVM参数调优** 与 **服务发现机制**,系统阐 阅读详情

背景

JVM DNS Cache机制,在应用程序使用域名来访问外部服务时可能会存在问题。

举个例子:

在做应用容灾秒级切换场景中,应用层通过域名访问中间件服务,若应用层DNS Cache没有及时更新,则无法做到秒级切换,因为DNS Cache中缓存的是旧的IP地址。

特别是,多数中间件服务会对外提供域名的方式来提供服务,对外屏蔽底层的高可用切换。应用程序往往是先解析域名,获得IP地址,再通过IP跟中间件进行数据传输。若IP地址迟迟没更新,即使中间件服务做了高可用切换,应用层还是感知不到。

本文对JVM DNS Cache机制进行探究分析。

JVM DNS解析域名是使用java.net.InetAddress这个类来实现域名解析服务。

常见的用法如下

       InetAddress inetAddress = InetAddress.getByName("youkuaiyun.com");
       System.out.println(inetAddress);

InetAddress源码剖析

查看InetAddress源码。

主要是这个内部类来缓存过期时间、地址。

验证

原理

通过定期解析域名地址,并设置休眠时间,查看缓存的过期时间

方法

通过反射机制查看Cache过期时间。

环境

使用JVM 11来作为验证环境

代码

import java.lang.reflect.Field;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.security.Security;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.text.SimpleDateFormat;
import java.util.concurrent.TimeUnit;


public class DnsCache {
    public static void main(String[] args) throws Exception {
        //   判断是否有Security Manager
        System.out.println(System.getSecurityManager());
        // negative取得到值
        System.out.println(Security.getProperty("networkaddress.cache.negative.ttl"));
        // 这个取不到值,返回结果是null
        System.out.println(Security.getProperty("networkaddress.cache.ttl"));
        printDns("www.baidu.com");

        System.out.println("Sleep 10 Second");
        TimeUnit.SECONDS.sleep(10);
        printDns("www.baidu.com");

        System.out.println("Sleep 19 Second");
        TimeUnit.SECONDS.sleep(19);
        printDns("www.baidu.com");

        System.out.println("Sleep 2 Second");
        TimeUnit.SECONDS.sleep(2);
        printDns("www.baidu.com");

        System.out.println("Sleep 10 Second");
        TimeUnit.SECONDS.sleep(10);
        printDns("www.baidu.com");
    }

    private static void printDns(String domain) throws UnknownHostException, NoSuchFieldException, IllegalAccessException {
        // do dns resolve
        InetAddress inetAddress = InetAddress.getByName(domain);
        System.out.println(inetAddress);
        Class inetAddressClass = java.net.InetAddress.class;
        final Field cacheField = inetAddressClass.getDeclaredField("cache");
        cacheField.setAccessible(true);
        final Map cacheMap = (Map) cacheField.get(inetAddressClass);
        cacheMap.forEach((k, v) -> {
            Class cacheEntryClass = v.getClass();
            try {
                Field expf = cacheEntryClass.getDeclaredField("expiryTime");
                expf.setAccessible(true);
                long expires = (Long) expf.get(v);
                Field af = cacheEntryClass.getDeclaredField("inetAddresses");
                af.setAccessible(true);
                InetAddress[] addresses = (InetAddress[]) af.get(v);
                List<String> ads = new ArrayList<String>(addresses.length);
                for (InetAddress add : addresses) {
                    ads.add(add.getHostAddress());
                }
                System.out.println(new Date() + ",Host:" + k + ", Cache Expires At:" + new Date(expires) + ",Address:" + ads);
            } catch (NoSuchFieldException e) {
                throw new RuntimeException(e);
            } catch (IllegalAccessException e) {
                throw new RuntimeException(e);
            }
        });
    }
}

结果

可以看到,在29秒前,Cache还是不变。

在31秒后,Cache发生了更改。

猜测缓存默认是30秒。

官方解释

JDK 8 & 11

Oracle JDK 8

https://docs.oracle.com/javase/8/docs/technotes/guides/net/properties.html

JDK 11 

Networking Properties (Java SE 11 & JDK 11 )

若设置-1,则永不过期(在JVM运行期间),需要重启JVM或者手动设置此值才会变更。

查看Security文件(java安装环境下,%JAVA_HOME%/conf/security/java.security)

大概翻译下:默认是永不过期。但是有个例外,如果没有设置Security Manager,则默认过期时间是30秒。

那么怎么查看有没有设置Security Manager呢

输出为Null,则表示没有设置,所以本文的JVM环境,DNS Cache TTL默认就是30秒

 System.out.println(System.getSecurityManager());

 其它版本JDK 

其它版本的JDK,可以在帮助中心,全局搜一下此参数。

Oracle Help Center - Search

JVM如何读取DNS TTL配置

源码

InetAddress中使用了sun.net.InetAddressCachePolicy来获取缓存策略,可以细看下这个类

读取过程

优先从Security Policy配置文件读取

networkaddress.cache.ttl

读取不到就读取系统变量

sun.net.inetaddr.ttl

若此系统变量还是读取不到,则判断有没有设置SecurityManager,没有的化,就设置默认值30.

如何查看JVM DNS TTL

有了上述的加载过程,就比较容易理解了。

import java.security.Security;

public class JVMDnsCacheManager {
    public static void main(String[] args) throws Exception {
        //   判断是否有Security Manager
        System.out.println(System.getSecurityManager());
        
        System.out.println(Security.getProperty("networkaddress.cache.ttl"));
        System.out.println(System.getProperty("sun.net.inetaddr.ttl"));
        
        // 设置后,可以取到值
        Security.setProperty("networkaddress.cache.ttl" , "20");
        System.out.println(Security.getProperty("networkaddress.cache.ttl"));
    }
}

如何修改JVM DNS TTL

方式一 使用代码更改TTL

注意,必须在使用InetAddress之前更改,若程序已经使用了InetAddress进行域名解析,则再使用程序的方式进行修改就不生效。(所以无法动态更改此参数,一旦设置,需要重启应用)

请看如下试验

import java.lang.reflect.Field;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.security.Security;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.text.SimpleDateFormat;
import java.util.concurrent.TimeUnit;


public class DnsCache {
    public static void main(String[] args) throws Exception {
        //   判断是否有Security Manager
        System.out.println(System.getSecurityManager());
        // negative取得到值
        System.out.println(Security.getProperty("networkaddress.cache.negative.ttl"));
        // 这个取不到值,返回结果是null
        System.out.println(Security.getProperty("networkaddress.cache.ttl"));

        //  change the Cache TTL to 10 Second
        System.out.println("We set the ttl to 10 Second");
        Security.setProperty("networkaddress.cache.ttl" , "10");
        printDns("www.baidu.com");

        System.out.println("Sleep 2 Second");
        TimeUnit.SECONDS.sleep(2);
        printDns("www.baidu.com");
        System.out.println("Sleep 9 Second,Total Sleep 11 Second");
        TimeUnit.SECONDS.sleep(9);
        printDns("www.baidu.com");
        TimeUnit.SECONDS.sleep(5);
        System.out.println("Sleep 5 Second,Total Sleep 16 Second");
        printDns("www.baidu.com");

        TimeUnit.SECONDS.sleep(15);

        // 验证在使用InetAddress进行域名解析后,再设置Cache TTL是否生效
        System.out.println("We set the ttl to 3 Second");
        Security.setProperty("networkaddress.cache.ttl" , "3");
        printDns("www.baidu.com");
        TimeUnit.SECONDS.sleep(5);
        System.out.println("Sleep 5 Second,Total Sleep 5 Second");
        printDns("www.baidu.com");
        TimeUnit.SECONDS.sleep(6);
        System.out.println("Sleep 6 Second,Total Sleep 11 Second");
        printDns("www.baidu.com");
    }

    private static void printDns(String domain) throws UnknownHostException, NoSuchFieldException, IllegalAccessException {
        // do dns resolve
        InetAddress inetAddress = InetAddress.getByName(domain);
        System.out.println(inetAddress);
        Class inetAddressClass = java.net.InetAddress.class;
        final Field cacheField = inetAddressClass.getDeclaredField("cache");
        cacheField.setAccessible(true);
        final Map cacheMap = (Map) cacheField.get(inetAddressClass);
        cacheMap.forEach((k, v) -> {
            Class cacheEntryClass = v.getClass();
            try {
                Field expf = cacheEntryClass.getDeclaredField("expiryTime");
                expf.setAccessible(true);
                long expires = (Long) expf.get(v);
                Field af = cacheEntryClass.getDeclaredField("inetAddresses");
                af.setAccessible(true);
                InetAddress[] addresses = (InetAddress[]) af.get(v);
                List<String> ads = new ArrayList<String>(addresses.length);
                for (InetAddress add : addresses) {
                    ads.add(add.getHostAddress());
                }
                System.out.println(new Date() + ",Host:" + k + ", Cache Expires At:" + new Date(expires) + ",Address:" + ads);
            } catch (NoSuchFieldException e) {
                throw new RuntimeException(e);
            } catch (IllegalAccessException e) {
                throw new RuntimeException(e);
            }
        });
    }
}

试验结果

所以最好在整个应用Init入口进行初始化设置,防止不生效。

方式二 修改Security配置文件

方式 三 设置JVM启动变量

如下所示,设置启动参数。

-Dsun.net.inetaddr.ttl=10

按照JVM读取DNS Cache TTL逻辑,正确读取到了sun.net.inetaddr.ttl设置的10秒

总结

影响JVM Dns Cache主要有两个值

  1. 一个是解析成功的的缓存时间(networkaddress.cache.ttl),默认不过期(-1);若没有设置Security Manager,则默认是30秒。
  2. 一个是解析不成功时的缓存时间(networkaddress.cache.negative.ttl),默认是10秒。设置成0,表示不缓存,设置成-1,表示一直缓存,不过期
  3. 推荐使用方式三,直接设置JVM启动参数的方式更改DNS Cache TTL值

Java DNS 负缓存问题分析与解决方案 阅读详情

相关推荐

Jmeter配置元件之DNS Cache Manager

当用户从不同的IP接收内容时,DNS缓存管理器元件允许测试在负载平衡器(CDN等)后面有多个服务器的应用程序。默认情况下,JMeter使用JVM DNS缓存。这就是集群中只有一台服务器接收负载的原因。DNS缓存管理器在每次迭代时分别解析每个线程的名称,并将解析结果保存到其内部DNS缓存中,该缓存独立于JVM和系统DNS缓存。 静态主机的映射可用于模拟/etc/hosts文件之类的。这些条目将优先于自定义解析程序。如果要使用此映射,则必须启用Use custom DNS resolver。 静态主机表的用法

岁月的博客 3143

JVM DNS缓存修改

第三方域名对应IP不定期发生变化时,需要将dns缓存时间设置为0,即不对域名进行缓存,每次都进行域名解析

孤海岛主 1142

【DDSCAT——离散偶极近似仿真程序04】参数理解和模型设计

在这一部分,我们开始理解DDSCAT程序设计中的一些参数问题。 承接第二部分内容中的ddscat.par文件,我们来聊一聊偶极子、实际体积、有效半径等关键词。 一、偶极子点阵 手册中说,我们需要设计模型(target/目标),它是有偶极子点阵组成的。偶极子,顾名思义,是由一对电荷组成的,但我们不用设计一对,我们设计一个点就行,...

XD_Yangf的博客 7552

jvm dns缓存问题解决方式

/设置解析成功的域名记录JVM中缓存的有效时间,JVM默认是永远有效,这样一来域名IP重定向必须重启JVM,这里修改为5秒钟有效,0表示禁止缓存,-1表示永远有效。2)在高并发时,不做DNS缓存时的CPU耗用比做了3s缓存的CPU耗用要高3/4倍,实时DNS请求相当耗用CPU;1)1个域名对应一个IP和一个域名对应12个IP,DNS查询响应时间差别极少,后者占用cpu稍高一点点;//设置解析失败的域名记录JVM中缓存的有效时间,JVM默认是10秒,0表示禁止缓存,-1表示永远有效。

weixin_57763462的博客 1994

数电实训:万年历

万年历

Lmyccq的博客 1万+

R语言 | 关联规则

关联规则(AssociationRules)是无监督的机器学习方法,用于知识发现,而非预测。 关联规则的学习器(learner)无需事先对训练数据进行打标签,因为无监督学习没有训练这个步骤。缺点是很难对关联规则学习器进行模型评估,一般都可以通过肉眼观测结果是否合理。 关联规则主要用来发现Pattern,最经典的应用是购物篮分析,当然其他类似于购物篮交易数据的案例也可以应用关联规则进行模式发现。

I think so I am 10万+

JVM DNS 缓存配置

域名解析并非一个简单的过程,其解析结果可能会被层层缓存,如浏览器 DNS 缓存、操作系统 DNS 缓存、ISP 的 DNS缓存,容易被忽略的是 JVM 本身也会对 DNS 进行缓存。启动程序,开始打印域名对应 IP 后,立刻修改 /etc/hosts,将。其中 cachePolicy 初始值为 -1,表示缓存永不失效。在 15 秒后,对 host 映射的修改才反应出来。在 10 秒后,对 host 映射的修改才反应出来。中体现,反编译后,有如下代码。

zhhui1123的博客 1558

低功耗设计-Power Switch

power gating与power switch cell

m0_61544122的博客 1万+

JVM如何设置DNS缓存失效时间

JVM为了提高效率,会将第一次的DNS结果缓存起来。

hongchangfirst 3105

YOLO26原创优化:SPPF优化 | 新一代高效可形变卷积DCNv4如何做二次创新?高效结合SPPF

如何跟YOLO26结合:1) SPPF高效结合

①答疑群聊服务;②YOLO大模型知识问答系统;③计算机视觉论文生成智能体; 356

如何提高电路的抗干扰能力

本内容详细介绍了电源传导干扰处理,包括滤波、Feedthrough电容器、磁环、磁珠、屏蔽的使用与选型,EMC电磁兼容测试项目简介与要求,单片机与电源抗干扰处理等。

让你爱上电路设计 8593

DNS 缓存、CDN 缓存、浏览器缓存,JVM DNS 缓存详解

最近测试遇到修改host文件后,清除浏览器缓存后,重启浏览器后,发现浏览器还是访问老DNS服务,于是网上查查原因,豁然开朗。 这里对互联网上一些文章进行整理,原文可查看参。 1、DNS 缓存 1.1 什么是DNS 全称 Domain Name System ,即域名系统。 万维网上作为域名和IP地址相互映射的一个分布式数据库,能够使用户更方便的访问互联网,而不用去记住能够被机器直接读取的IP数串。DNS协议运行在UDP协议之上,使用端口号53。 简单的说,通过域名,最终得到该域名对应的IP.

zzhongcy的专栏 8151

C#串口通信从入门到精通(1)——硬件接线

RS-232接口一般都是9针的,有公母头(针头和孔头),为了便有理解以下都称为针头和孔头,针头就是露出来的针,孔头就是9个孔,总共使用3条线进行通信,一条用于发送,一条用于接收,另外一根是GND地线,由于线路的功能是永久性的,设置连接时,必须确保一个节点的发送线与另一个节点的接收线相连,反之亦然,RxD(PC的接收线)连接到TxD(传感器电子设备的发送线),TxD(PC的发送线)连接到RxD(传感器电子设备的发送线)。两条线路的电平都是相对于GND的。因此,GND也必须连接,但不能将GND与屏蔽连接。

qq_34059233的博客 1万+

Java DNS cache 时效设置备忘

Java DNS cache 时效设置备忘 我们知道java的InetAddress会通过自身的cache缓存dns解析结果。 缓存的策略主要有两种,一种是缓存正确解析后的IP地址,还有一种是缓存解析失败后的状态。 这两种策略的时效配置都在 %JRE%\lib\security\java.security 这个文件里。 TTL=Time to Live networkaddress.ca

JonnyWei的专栏 1万+

一文吃透 SAP HANA SDA:把分散数据当作本地数据来用的那把钥匙

摘要:SAP HANA SDA(Smart Data Access)技术详解:150字精要 SAP HANA SDA是一种数据虚拟化技术,允许在不复制数据的情况下访问远端数据源。核心功能包括: 通过Remote Source定义连接配置 创建Virtual Table作为本地代理 支持谓词下推优化查询性能 与SDI技术协同工作扩展数据集成能力 典型应用场景包括: 跨系统联邦查询 冷热数据分层管理 混合云数据整合 远程表复制(RTR)实现近实时数据同步 实施要点: 需关注适配器能力差异 合理运用查询下推优化

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 318

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

httpclient DNS cache问题解决办法

DNS缓存在操作系统和JDK内部已经实现了吧,一般不需要再由程序介入了。 the JVM will cache the dns information for meautomatically after the first query 也就是说,httpclient去抓取每个url时,...

406

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

从 UnknownHostException 错误来分析 Java 的 DNS 解析和缓存机制

01概述接连几个客户在直接使用 Amazon Java SDK 或者其他应用依赖 Amazon Java SDK 时,偶尔会遇到 API 端点无法解析的错误,也就是 Java 报出的 UnknownHostException 异常。这种问题偶尔发生,很难追踪和定位故障。本文从几个问题出发,希望能给予大家一个非常合适的解决方案。为了方便快速阅读,先将问题和简单答案给出,后续再细细分析。Q:Amazo...

亚马逊云科技专栏 1499

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

Java DNS cache 时效

Java DNS cache 时效 我们知道Java的InetAddress会通过自身的cache缓存dns解析结果。 缓存的策略主要有两种,一种是缓存正确解析后的IP地址,还有一种是缓存解析失败后的状态。 这两种策略的时效配置都在 %JRE%\lib\security\java.security 这个文件里。 TTL=Time to Live networkaddress.cache.

第三眼的思绪 1035

Kubernetes中Nacos集群DNS解析问题解决方案

在分布式系统中,服务发现是微服务架构的核心组件之一,而DNS解析作为服务发现的基础机制,其稳定性直接影响系统可用性。Kubernetes通过CoreDNS实现内部服务发现,但Java应用的DNS缓存机制可能导致解析异常。本文以Nacos 3.1.1集群部署为例,深入分析K8s服务发现原理与Java DNS缓存特性的交互问题,提供包括JVM参数调优、Headless Service配置、就绪探针设置等工程实践方案,解决常见的UnknownHostException异常。针对生产环境,还给出DNS策略优化、客户

weixin_34101914的博客 190

Java DNS 缓存机制深度解析:networkaddress.cache.ttl 参数调优实战

本文深入解析Java DNS缓存机制,重点探讨`networkaddress.cache.ttl`参数的调优实战。通过分析`java.net.UnknownHostException`异常的根本原因,提供生产环境推荐配置和动态调整技巧,帮助开发者优化网络性能和可靠性。适用于云原生环境和传统微服务架构。

weixin_32308101的博客 301

java 设置dns_通过代码直接设置Java的DNS - Java Dns Cache Manipulator

通过代码直接设置Java的DNS - Java Dns Cache Manipulator 通过代码直接设置Java的DNS(实际上设置的是DNSCache),支持JDK 6+。通过代码直接设置Java的DNS - Java Dns Cache Manipulator 功能 设置/重置DNS(不会再去Lookup DNS)可以设置单条 或是通过Properties文件批量设置 查看DNS Cach...

weixin_33138675的博客 984

阿里巴巴Java DNS Cache Manipulator安装与使用指南

在克隆或下载了`java-dns-cache-manipulator`项目之后,你会看到以下主要的目录和文件结构: ### `library` 这是核心库的源代码所在目录.它包含了所有用于操作JVM DNS缓存的功能性代码. #### `src/main/java` 这个子目录下包含了主应用的所有源代码,包括但不限于`com.alibaba.dcm.DnsCacheManipulator`...

gitblog_00341的博客 1169

Oracle JDBC连接DNS解析性能优化实践

DNS解析是网络通信的基础环节,其工作原理是将域名转换为IP地址以便建立连接。在Java应用中,默认的DNS缓存策略可能导致高并发场景下的性能问题。Oracle JDBC驱动在连接建立时会频繁触发DNS查询,这种设计在数据库访问场景可能引发连接风暴。通过调整JVM级DNS缓存参数和实现自定义解析器,可以有效减少重复查询。该优化方案特别适用于使用HikariCP等连接池的微服务架构,能显著降低数据库连接建立耗时。生产环境数据显示,优化后DNS查询次数从每分钟3200次降至2次,平均连接耗时从420ms优化到3

weixin_31421613的博客 244

java程序配置dns后超时,如何使Java遵守DNS缓存超时?

We use GSLB for geo-distribution and load-balancing. Each service is assigned a fixed domain name. Through some DNS magic, the domain name is resolved into an IP that's closest to the server with leas...

weixin_39636707的博客 390

java代码手动添加hosts中没有的hostname和ip, 添加DNS缓存

主要是通过工具修改 https://github.com/alibaba/java-dns-cache-manipulator/tree/master/library 简单说就是下载一个工具, 然后用工具中的方法就可以动态添加hostname和ip映射 jar包下载地址 https://mvnrepository.com/artifact/com.alibaba/dns-cache-man...

稼轩 5343
上一篇: SonarQube MyBatis插件
下一篇: RocketMQ Dashboard开启登录认证
Jeff Dauglas
博客等级 码龄14年 1176粉丝 11原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值