JAVA DNS缓存原理

一、DNS简介

    日常上网大家一般都是使用域名,比如www.baidu.com。当你在浏览器输入了www.baidu.com的时候,就是用到了DNS技术。将域名解析为ip地址。

     域名是分等级的,分为:根域名、顶级域名、次级域名、主机名。一般格式如下:主机名.次级域名.顶级域名.根域名。

二、JAVA中使用DNS

有两种方式:

使用InetAddress的getByName方法

InetAddress inetAddress = InetAddress.getByName("unKnownHost");

Socket ss = newSocket(inetAddress,123);

直接使用Socket封装好的(不推荐):

Sockets = newSocket("unKnownHost",123);

三、JAVA对DNS的缓存

java获取host对应ip的过程如下(只关注查找ip的过程):

1.通过host先去本地缓存中获取,本地缓存分为addressCache(有效缓存)和negativeCache(无效缓存)

    1.1如果addressCache中存在,则返回缓存的结果

    1.2如果negativeCache中存在,则返回unknown_array,外层会抛出UnKnownHostException

     1.3如果两个缓存均不存在,则返回null

2.如果缓存返回的为null,则去nameService中去查询。这里有一个小优化,jdk维护了一个lookupTable对象,存放正在查询的域名。

    2.1 如果lookupTable中存在host,则说明有另外一个线程在查询,当前线程等待另外一个线程完成。

    2.2 如果lookupTable中不存在host,则将该host放入lookupTable中,并去nameService中查询,查询nameService后,无论结果,均会唤醒所有在等待的线程。

    2.3这样做的好处,防止同样的host并发去查询dns,这也是一种防止缓存雪崩的技术。

四、缓存策略

那么有读者就要问了,因为ip有可能改变,那么缓存的时间是怎么控制的。那就看另外一个类:InetAddressCachePolicy

有四个参数可以控制缓存时间(-1 永久有效;0 不缓存;其余正值 缓存时间):

networkaddress.cache.ttl     有效缓存时间(优先级高)

sun.net.inetaddr.ttl   有效缓存时间(优先级低)

networkaddress.cache.negative.ttl 无效缓存时间(优先级高)

sun.net.inetaddr.negative.ttl  无效缓存时间(优先级低)

这四个参数,均可以通过启动java程序中,增加-D参数进行传入

五、坑

还记得前边说的不建议直接使用socket的String类型host构造函数吗?我认为哪个是坑。代码中可以看到,异常被吞掉了,虽然对外的结果都是UnknownHostException,但是缺少了第一手的堆栈信息,很难区分是由于缓存的无效地址还是因为查找失败。

推荐阅读更多精彩内容