DNS解析异常
部分DNS解析在高并发下有性能瓶颈,确保系统的DNS是可靠的,比如,k8s dns解析策略,确保是高性能的,避免无效的查询。另外,部分域名可能会启用 DNS 负载均衡,即每次解析返回的多个IP地址的顺序不同,过大的ttl会影响负载均衡效果。除了应用层的缓存外,也可尝试 JVM自身的DNS缓存 (这个是全局的),通过命令行来控制缓存过期时间, see。DNS解析失败未必会产生负面影响,比如,可能当时
背景知识 (background)
网络请求的第一步,通常是进行DNS解析,即 InetAddress.getAllByName
,解析成功后放入Positive Cache,默认缓存30s(可调整/禁用)。
若DNS解析失败,会放入Negative Cache,默认缓存10秒(可调整/禁用),后续DNS解析直接返回UnknownHostException
。也就是说,极端情况下,DNS解析失败会导致10秒不可用。
SRE托管的JVM应用通常禁用了DNS缓存,其他自运维的应用建议禁用Negative Cache。
查看指标 (dashboard)
展开: 网络 / 域名 / DNS
这一行,找到监控面板:
[DNS耗时统计]
其中,近五分钟解析失败
是最近五分钟DNS解析失败的次数。
止损措施 (action)
DNS解析通常是偶发的,开发能做的有限,可向运维反馈,持续观察。
事后改进(postmortem)
DNS解析失败未必会产生负面影响,比如,可能当时只有DNS健康检查,没有业务请求在执行。
参考原因(cause)部分,针对性的优化。
可能的原因 (cause)
一、配置文件有误、DNS误操作
用户配置有误的,比如数据库、Redis、第三方域名弄错了,修复后重新发布即可。
DNS误操作的,联系OP及时回滚。
二、网络抖动或DNS解析瓶颈
跨机房请求容易受到网络抖动影响,比如腾讯云访问亦庄机房的。
部分DNS解析在高并发下有性能瓶颈,确保系统的DNS是可靠的,比如,k8s dns解析策略,确保是高性能的,避免无效的查询。
实践中,追求极致的DNS高可用时,可适当引入应用层缓存。比如:ApacheHttpClient 、Netty 在构造时,提供异步DnsResolver,伪代码如下:
public InetAddress[] resolve(String host) throws UnknownHostException {
//缓存不存在,则去加载 ; 如果存在,则返回旧解析,同时检查是否到过期时间了,触发异步任务去加载
DnsCacheEntry record = this.dnsCache.get(host);
if (record == null) {
InetAddress[] addresses = InetAddress.getAllByName(host);
if (addresses != null && addresses.length > 0) {
this.dnsCache.put(host, new DnsCacheEntry(addresses));
}
return addresses;
} else {
// 检查下是否应该触发异步刷新
if (record.isExpired(this.dnsTtlMs)) {
try {
this.dnsAsyncResolveExecutor.submit(new DnsResolveTask(host, (domain, ipList) -> {
dnsCache.put(domain, new DnsCacheEntry(ipList));
}));
} catch (Exception e) {
// ignore , 如果异常抛出,比如队列满了等,则返回之前的数据
}
}
return record.getIpList();
}
}
除了应用层的缓存外,也可尝试 JVM自身的DNS缓存 (这个是全局的),通过命令行来控制缓存过期时间, see Networking Properties - Oracle 。
#0 = 禁用, -1 = 永久缓存,>0 缓存多少秒
-Dsun.net.inetaddr.ttl= 10
#禁用掉negative缓存, 0 = 禁用, -1 = 永久缓存,>0 缓存多少秒
-Dsun.net.inetaddr.negative.ttl=0
警告:请设置合理的缓存ttl ,兼顾运维变更的实时性和性能
,目前 Redis / 数据库等基础设施的灾备切换是通过调整DNS指向来实现的 。
另外,部分域名可能会启用 DNS 负载均衡,即每次解析返回的多个IP地址的顺序不同,过大的ttl会影响负载均衡效果。
更多推荐
所有评论(0)