某个java工程配置中用到2个域名,一个是外部域名 outer.example.com,一个是内部域名 inner.example.com。
外部域名解析走DNS,/etc/resolv.conf
内部域名解析走本地hosts, /etc/hosts
这个组合确实有点。。。。 但实际情况就是如此: inner.example.com 没有加到 DNS的 example.com 这个zone做解析,对它的解析只能走本地 /etc/hosts 。
$ cat /etc/resolv.conf
search cloud.example.com
nameserver xx.xx.xx.xx
nameserver xx.xx.xx.xx
$ cat /etc/hosts
inner.example.com xx.xx.xx.xx
启动工程,运行正常,解析 outer.example.com 、 inner.example.com 均正常
运行一段时间后,某天突然日志报 “java.net.UnknownHostException ,无法解析 inner.example.com ”
ping inner.example.com ,完全正常
重启工程后, “java.net.UnknownHostException ,无法解析 inner.example.com ” 消失 ,但是不知道下次什么时候又会突然出现!
疑惑点:
-
ping inner.example.com 正常的情况下,为什么工程运行会突然无法解析 inner.example.com
-
inner.example.com 的解析是本地写 hosts的,优先级不是最高吗?
-
为什么重启工程,就又可以解析 inner.example.com 了,但是过一阵又可能无法解析了
-
难道工程运行过程中,突然找 DNS 去解析 inner.example.com? 那确实会无法解析,因为这个解析只写在本地hosts
猜想可能原因:
工程运行过程中,突然找 DNS 去解析 inner.example.com, 那确实会无法解析,因为这个解析只写在本地hosts 。
工程启动时:
优先读 /etc/hosts 做解析,可以解析 inner.example.com
读 /etc/resolv.conf ,解析 outer.example.com
这些解析会作为缓存存在JVM 中一段时间,缓存失效后,程序会去找 /etc/resolv.conf 要 inner.example.com 和 outer.example.com 的解析,此时就会无法解析 inner.example.com 了!
当你重启工程,就会重复上面 工程启动时的 解析缓存加载过程,直到缓存失效,日志开始报 “java.net.UnknownHostException ,无法解析 inner.example.com ”。
Linux - JRE - JVM - JAR 四者的关系:
image.png当我们的服务运行,发出对外请求,带有域名的请求:
image.png上面的JAR就相当于是我们的一个服务。
服务发起请求,其先通 JVM cache 找到 DNS 解析服务器的IP,DNS 解析完域名到 internet 找到目标服务ip地址,从而实现通信。
现在DNS解析服务器换了IP地址, 在 Linux上 ping www.example.com 是新的DNS解析没有问题,但是 JVM 缓存旧 DNS IP, 去网段找不到 DNS 服务器了,域名自然就无法解析,从而 出现 java.net.UnknownHostException
这就是为什么 Linux 上 ping 可以,JVM 不一定可以的原因。
java对DNS解析IP进行缓存,默认缓存超时时间为-1(在重启JVM前永久缓存)。
在第一次访问某域名后将会缓存解析到的IP地址,之后直接从缓存里获得所需的信息(如IP地址),而无需再访问DNS服务器,
但如果突然DNS解析IP的地址有变更的话,提交的地址仍为原解析的IP地址,这将会访问到无效的IP地址而报错。
参考
如何排查我的 Java 应用程序中的 UnknownHostException 错误?
https://aws.amazon.com/cn/premiumsupport/knowledge-center/route-53-fix-unknownhostexception-error/
java.net.UnknownHostException
https://blog.csdn.net/hawinlolo/article/details/122254968
Setting the JVM TTL for DNS Name Lookups
https://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/java-dg-jvm-ttl.html
网友评论