App网络优化是体验中很重要的一部分, 最近做了一些网络优化相关的工作, 想把最近的工作总结一下;

1. 分析app网络现状: 

通过对最新版本最近一周的网络数据统计, 

网络错误率中各项占比:

  • 未知主机: 1.33%
  • 请求超时: 0.33%
  • SSL证书错误: 0.13%
  • 建立连接失败: 0.23%

平均网络请求响应时间:

  • 1237ms

从数据看, 最高的网络错误来自于未知主机, 请求响应时长偏高;

然后通过各种更多维度的数据查看发现, 总结出了下面几个问题:

  • 慢请求中有很多是DNS时间超长, 最长的有几百秒
  • 错误请求中, DNS错误占比最高

当然,还有其他一些错误和响应时长的问题, 比如http错误, 需要通过错误码从业务方面解决; 请求连接时长,传输和处理时长, 这些可以通过服务端优化;本次哇们主要做的是DNS相关的优化

2.DNS如何优化 

2.1 关于DNS原理简单介绍: 

关于DNS的相关介绍:https://www.51cto.com/article/674906.html

传统的DNS解析:

  • 当开始 DNS 解析的时候,如果 LocalDNS 没有缓存,那就会向 LocalDNS 服务器请求(通常就是运营商),如果还是没有,就会一级一级的,从根域名查对应的顶级域名,再从顶级域名查权威域名服务器,最后通过权威域名服务器,获取具体域名对应的 IP 地址。

android dns 解析失败 修改dns 安卓本地dns解析_服务器

  • 传统DNS缺点: 不稳定(DNS服务器被劫持或故障), 访问慢

2.2 传统DNS替代

使用HttpDNS解析:

  • HttpDNS其实也是对DNS解析的另一种实现方式,只是将域名解析的协议由DNS协议换成了Http协议,并不复杂。使用HTTP协议向D+服务器的80端口进行请求,代替传统的DNS协议向DNS服务器的53端口进行请求,绕开了运营商的Local DNS,从而避免了使用运营商Local DNS造成的劫持和跨网问题;

android dns 解析失败 修改dns 安卓本地dns解析_dns服务器_02

 HttpDNS核心是需要稳定且速度快的DNS服务器, 一般都是需要收费的;  目前有阿里DNS,腾讯云DNS等选择; (我没有尝试过收费的); 免费的有开源的七牛sdk, 需要自己配置服务器与连接方式;

  • 七牛开源地址:  https://github.com/qiniu/happy-dns-android
DnsManager dns;
if(DnsManager.needHttpDns()){
	IResolver[] resolvers = new IResolver[2];
    // dohResolver 需要配置一个支持 Doh(Dns over http) 协议的 url
    resolvers[0] = new DnhResolver("https://dns.alidns.com/dns-query");
    resolvers[1] = AndroidDnsServer.defaultResolver(getContext());
    dns = new DnsManager(NetworkInfo.normal, resolvers);
}else{
	IResolver[] resolvers = new IResolver[2];
    resolvers[0] = AndroidDnsServer.defaultResolver(getContext());
    resolvers[1] = new DnsUdpResolver("8.8.8.8");
    dns = new DnsManager(NetworkInfo.normal, resolvers);
}

可支持httpDNS服务器解析(DnhResolver), 也支持自定义udp服务器(DnsUdpResolver);

对于我们项目来说, 目前没有速度快且稳定的httpDns服务器, 为了速度和成功率, 我们增加了udp服务器的配置,通过一些业务策略, 可以修改dns服务器的顺序以及数量, 然后通过观察对比选出较合适的服务器;

3. DNS再次优化

3.1 上线分析

通过增加dns服务器解析兜底策略, 发现DNS的错误率降低了一半,颇具效果;  但是看另一个数据就不是那么乐观了, 网络请求响应时间也增加了近一倍; 这不是我们想看到的, 紧急关掉了配置, 网络又恢复了之前水平;

经过观察, 增加了时长都集中在DNS解析中; 经过本地测试, 系统的dns时长一般都在10ms内, 而三方的dns服务器时长在30~100ms, 这是在网络良好的情况下; 线上网络复杂的情况下, 这个差距肯定还会增大; 所以照这样看来, 系统dns解析还是所有dns的首选; 

而且慢请求中, DNS解析有记录会超过几百秒, 但是项目中okhttp的超时时间connectTimeout已经设置了30s, 说明很遗憾, 这个超时对DNS没有作用; 也就是说 dns,没有超时时间;

3.2 解决方案

  1. 调整DNS服务器解析顺序, 将系统解析放在首位
  2. 设置DNS超时时间, 规避超长慢请求

经过两次的调整, 新版本上线后, 网络错误率下降了一倍, 响应时间也降低了30%; 目前还在观察中中, 后续持续优化中;

3.3 优化源码

关于DNS优化的源码, 可以参考