Android应用频繁出现java.net.UnknownHostException DNS解析异常求助
排查与解决Android应用偶发UnknownHostException问题
问题概况
Android应用通过Crashlytics捕获到频繁的非致命java.net.UnknownHostException,仅部分用户受影响,出现时间无规律。部分用户通过重装应用或使用VPN可恢复连接,但Postman等工具能正常访问后端。后端基础路径为http://abc.xyz.in:8080,基于AWS Elastic Beanstalk部署,域名在GoDaddy购买,由Route53负责解析。
异常核心堆栈指向自定义HttpDNS实现:
org.xbill.DNS.Address.lookupHostName (Address.java:272) org.xbill.DNS.Address.getByName (Address.java:311) stock.ledger.commons.CustomHttpDns.lookup (CustomHttpDns.kt:62)
排查方向
1. 自定义HttpDNS逻辑缺陷
从堆栈看,异常触发于自定义DNS解析环节,重点检查:
- 缓存策略:是否存在旧IP缓存未及时更新,导致解析失效?
- 异常处理:解析失败时是否直接抛异常,未回退到系统默认DNS?
- 网络适配:是否在特定网络环境(如移动数据、小众运营商)下,自定义DNS服务器不可达?
2. 域名解析链路问题
检查GoDaddy+Route53的解析链路:
- 域名服务器指向:确认GoDaddy已将域名的DNS服务器完全配置为Route53的权威服务器,避免混合解析异常。
- Route53 TTL设置:若TTL过长,后端IP变更后客户端缓存无法及时更新;过短则增加解析开销,建议设置为5-15分钟。
- Route53健康检查:验证是否正确剔除了不健康的后端实例IP,避免返回无效地址。
3. Android系统与网络环境问题
- 系统DNS缓存:Android系统及应用层面的DNS缓存可能留存失效IP,重装应用会清除应用缓存,VPN会切换DNS服务器,这解释了临时解决方案的有效性。
- 运营商DNS异常:部分区域的运营商DNS可能存在解析故障,导致特定用户无法正常解析域名。
4. OkHttp配置问题
- 重试策略:默认
RetryAndFollowUpInterceptor不会重试UnknownHostException,需确认是否配置了自定义重试逻辑。 - DNS fallback:是否强制依赖自定义DNS,未配置系统DNS作为兜底方案?
解决方法
1. 修复自定义HttpDNS实现
添加解析失败回退机制、合理缓存策略及重试逻辑:
class CustomHttpDns : Dns { private val dnsCache = mutableMapOf<String, Pair<List<InetAddress>, Long>>() private val cacheExpireTime = 10 * 60 * 1000 // 缓存10分钟 override fun lookup(hostname: String): List<InetAddress> { // 优先读取有效缓存 val cachedEntry = dnsCache[hostname] if (cachedEntry != null && System.currentTimeMillis() - cachedEntry.second < cacheExpireTime) { return cachedEntry.first } return try { // 自定义DNS解析 val addresses = Address.getAllByName(hostname).toList() dnsCache[hostname] = addresses to System.currentTimeMillis() addresses } catch (e: UnknownHostException) { // 回退到系统默认DNS解析 InetAddress.getAllByName(hostname).toList() } } }
2. 优化域名解析配置
- 在Route53中将域名记录TTL设置为10分钟,平衡缓存有效性与更新速度。
- 确认GoDaddy域名的DNS服务器完全指向Route53提供的权威服务器,无残留第三方DNS配置。
- 开启Route53健康检查,确保仅返回健康的后端实例IP。
3. 处理系统DNS缓存
- 监听网络连接变化(通过
ConnectivityManager.NetworkCallback),在网络切换时清空应用内的DNS缓存。 - 为用户提供手动刷新DNS缓存的入口(如设置页按钮),快速解决缓存失效问题。
4. 调整OkHttp配置
- 自定义重试拦截器,针对
UnknownHostException进行最多3次递增间隔重试(如1s、2s、4s)。 - 确保OkHttp的DNS配置中,自定义DNS失效时能自动回退到系统DNS。
5. 增强监控与日志
- 在
CustomHttpDns中添加详细日志,记录解析请求的hostname、网络类型、解析结果、异常信息,便于定位问题场景。 - 收集异常用户的设备信息(Android版本、运营商、地区),缩小问题范围。
内容的提问来源于stack exchange,提问作者sake007
相关产品推荐
相关产品推荐

