在使用win10系统开发中,当我们不使用注册中心部署 spring-boot-admin 和相对应的客户端时,可能会出现 admin-server 无法拉取客户端侧监控信息的问题,解决方案很简单,只需要在客户端测添加以下一行配置就行:
spring.boot.admin.client.instance.prefer-ip: true # 使用ip注册
分析原因
当启动客户端后,我们发现 server 端出现以下错误
failed to resolve 'xxx.mshome.net' after 4 queries ; nested exception is java.net.UnknownHostException: failed to resolve 'LAPTOP-CDQ9PAID.mshome.net' after 4 queries
看来是 xxx.mshome.net 导致的一个问题,我们查询本机的 dns 缓存,发现了以下一段记录:
1.224.17.172.in-addr.arpa
----------------------------------------
记录名称. . . . . . . : 1.224.17.172.in-addr.arpa.
记录类型. . . . . . . : 12
生存时间. . . . . . . : 0
数据长度. . . . . . . : 8
部分. . . . . . . . . : 答案
PTR 记录 . . . . . . : xxx.mshome.net
先解释两个域名:in-addr.arpa 和 mshome.net
in-addr.arpa
.arpa 是一个专门用于互联网基础设施的一个顶级域名。现在他有两个二级域名:
- in-addr.arpa。IPv4 DNS 反向查询
- ip6.arpa。IPv6 DNS 反向查询 DNS域名解析是将域名解析出ip,而反向查询就是将ip解析成域名。
mshome.net
这个域名是微软的,当我们使用 windows网络连接共享(ICS)时,如果本机没有域名,系统会自动配置这个域名。
解决
spring-admin server 打印错误信息,无法处理 xxx.mshome.net 域名,我们深入了解一下处理过程。因为server与client是以心跳的方式交互的,我们只需要关注 client 是如何拿到这个域名的。
在 client 启动时,服务会自动注册一个 DefaultApplicationRegistrator,这个bean会调用 DefaultApplicationRegistrator#register 方法将 ApplicationFactory#createApplication创建的Application 注册到 server端,Application#managementUrl就是刚才这个 xxx.mshome.net 域名。
通过调用链,我们发现最终调用的是 InetAddress#getLocalHost,在这里会拿取 localAddrs[0],这个地址刚好是 xxx.mshome.net 代表的地址。
那么为什么配置了上面的参数就没问题了,主要是DefaultApplicationFactory#getHost这个方法:
protected String getHost(InetAddress address) {
return this.instance.isPreferIp() ? address.getHostAddress() : address.getCanonicalHostName(); // 当prefer-ip=true时,使用ip而不是域名,这里是172.17.224.1
}
再次探讨 mshome.net 怎么来的
ipconfig 打印网络配置
以太网适配器 vEthernet (WSL):
连接特定的 DNS 后缀 . . . . . . . :
本地链接 IPv6 地址. . . . . . . . : fe80::618e:d3dc:c21b:b510%68
IPv4 地址 . . . . . . . . . . . . : 172.17.224.1
子网掩码 . . . . . . . . . . . . : 255.255.240.0
默认网关. . . . . . . . . . . . . :
发现这是 WSL 的网络!
总结
最好加上这个配置,以防出现未知错误
spring.boot.admin.client.instance.prefer-ip: true # 使用ip