JAVA中DNS缓存设置(转)
原文:https://blog.csdn.net/guanfengliang1988/article/details/92813431
作者:夜风_BLOG
我们上网的原点就是打开浏览器,在上方地址栏输入网址的那一刻,这个回车按了之后,发生了很多事情。首先,计算机只懂0和1,也就是说人类的字母网址计算机是不懂的,它只认识IP地址,如果是IPV4那就是4组8位的二进制数字。为了人类方便,需要有一个把网址翻译成IP地址的服务,就是DNS。其工作原理如图
这是一个高度简略的示意图,实际上DNS整个获取过程是被层层缓存的,一个DNS的获取并不一定都是从权威处获得的响应。再来一个复杂点的示意图:
Java DNS缓存
Java的网络应用程序的DNS缓存是由JVM的缓存策略控制的,当InetAddress类第一次使用某个域名(如www.google.com)创建InetAddress对象后,JVM就会将这个域名和它从DNS上获得的信息(如IP地址)都保存在DNS缓存中。当下一次InetAddress类再使用这个域名时,就直接从DNS缓存里获得所需的信息,而无需再访问DNS服务器。
以获取一个域名www.jd.com对应的ip为例,其代码踪迹是这样的:
InetAddress.getByName(“www. XXX.com”) InetAddress.getAllByName(“www. XXX.com”)[0] InetAddress.getAllByName(“www. XXX.com”, null) InetAddress.getAllByName0(“www. XXX.com”, null, true) InetAddress.getCachedAddresses(“www. XXX.com”)
InetAddress. getCachedAddresses的源码如下
可以看到cache有两个,即有效DNS解析的cache(addressCache)和无效DNS解析的cache(negativeCache),为了让dns解析效率更高java很聪明的把dns解析正确的域名保存下来了,方便后续再查时能最快的返回结果;同时也缓存了无效的域名,因为根据DNS解析的原理,往往无效的域名解析耗时比正常的域名解析时间要长,所以缓存无效的域名可以有效的避免浪费时间在查找无效域名上,提升代码性能。下面是java.net.InetAddress$Cache的源码:
从上面的Cache类的get方法可以看到:
如果policy为0,那么cache的get方法就永远返回null,相当于cache不起作用了;
如果policy为-1,那么cache缓存过的entry永远都不会过期,也就是说就算域名对应的ip变了,cache再也不更新ip了
如果policy为n,根据“System.currentTimeMillis() + (policy * 1000)”,那么这个entry就可以在cache中存活n秒钟,即n秒后,该entry会被移除出cache
问题是policy怎么来的,看方法Cache.getPolicy()方法里面,主要是InetAddressCachePolicy类的get()和getNegative()方法。看sun.net.InetAddressCachePolicy类的源
一个是在java.security文件中配置networkaddress.cache.ttl=1111和networkaddress.cache.negative.ttl=2222
另一个是在启动参数中添加这两个参数-Dsun.net.inetaddr.ttl=1111和-Dsun.net.inetaddr.negative.ttl=2222
而且这两中配置方法有一个优先级,即第一种方法优先级高,但是第一种方法需要在打开Java中的SecurityManager,若没有打开则${java.home}/jre/lib/security/java.security文件的配置将不会生效