参考原文@ 移动4G网络App页面加载时间过长 前言
移动4G网络App页面加载时间过长 解决办法
一. 前言
移动4G网络App页面加载时间过长
发现问题
2016年12月份开始,使用android客户端的部分用户反映在使用移动4G网络的情况下,App内的页面加载时间过长,几乎加载不出来,导致无法正常使用App。
查找原因
1、由于目前只有使用Android客户端的用户反映此问题,首先想到是否为12月份上线的App存在bug,经对比,上线功能不涉及此问题页面的代码,且在下边的(3)中进行测试时,发现有问题的手机使用早些版本的客户端的时候一样存在该问题,因此Android客户端的bug排除在外。
2、是否是因为App配套的Service服务有问题,但是IOS、Android使用的是同一套,因此也排除在外。
3、公司内部使用有问题的手机、SIM卡,没有问题的手机、SIM卡进行交叉对比测试发现:有问题的手机内的SIM卡放在其他手机是可以正常访问的,没有问题的SIM卡放在有问题的手机内也会出现不能访问。因此应该是手机的问题。但是问题是从12月份开始出现的,这样又否定了手机的问题。
4、至此,那问题一定是出在12月份上线的某些东西上了。将12月份的工作逐渐测试、筛选,突然发现有问题的手机网络请求走的是IPV6而非IPV4,在经过测试,问题就出现在IPV6上!
查看手机的APN中的协议:
开启IPV4 加载系统设置-移动网络-sim卡管理-接入点名称(APN)-修改接入点-APN协议(IPv4/IPv6),如果默认的是IPv6或者是IPv4/IPv6,就更改为IPv4保存,然后再去打开App查看网络数据加载是否正常了。
总结
1、12月份因为IOS上线审核,网站启用IPV6.
2、Android系统的开源性,部分手机-设置-移动网络-Sim卡管理-接入点名称(APN)-修改接入点-APN协议(IPv4/IPv6)-有的系统默认使用的是IPv6,而IPv6目前在国内的网络大部分还没有升级到IPv6,所以可能走的网络线路是:国内-国外-国内,这样绕了一大圈才请求到数据,所以造成页面加载时间过长.
3、中国移动升级4G+.综合以上的多方面原因,导致出现此次问题。
解决
现阶段方案: IOS上线审核阶段暂时开启IPV6,审核通过上线之后再关闭IPV6。
二. Android部分手机4G网第一次请求很慢(wifi正常)解决方案
背景
最近,客户突然反馈一个问题,手机4G网网络请求特别慢,卡了快30s左右,之后网络请求就正常了,但是项目杀掉,重新打开,又卡了30s左右,问题反馈过来一脸懵逼状态,从来没有遇到过这种情况,然而手边所有测试机都属于正常现象,于是开始研究什么问题造成的
分析
网上查了查,答案都指向了DNS解析设置的问题,解析有两种 ipv4 ipv6 ,android默认不支持ipv6解析,之后问了下后台配置,说IOS 的 appstore 审核,必须需要ipv6的配置才能正常进行,所以服务端增加了 ipv6 支持,同时也支持ipv4,但是ipv6的入口再美国,那这样看来,猜测是否是android手机默认通过ipv6去连接后端服务器,绕了一大圈才返回结果?于是,各个问题都分别科普下
1、android为何不支持ipv6解析
IPv4地址即将枯竭,这种警告已经发出了一次又一次,但是IPv6依然迟迟无法普及,原因之一就是有些巨头不提供支持。
Windows、Linux、Mac OS X、iOS等系统都已经支持了IPv6,但是Google Android却迟迟不肯加入。要知道,Android设备的规模已达几十亿,占据了智能手机市场的几乎八成,它不支持IPv6无疑是极大的桎梏。
由于不支持新的IP地址动态分配协议DHCPv6,Android设备在无线网络中经常处于不利地位,这也让很多网络管理人员很郁闷。为此,不少公司甚至禁止在企业网络中使用Android设备,这也给他们的IPv6部署产生了很大的阻碍。
不少专业人士对Google的迟缓感到十分不满,尤其是在Google Code的一个帖子中,很多人甚至愤怒得破口大骂。
不过在Google开发者、IPv6权威专家Lorenzo Colliti看来,Android不支持IPv6也是有苦衷的,比如会影响那些依赖IPv4的应用,无法强制开发者采用IPv6网络地址,地址转换后性能会有损失等等。
2、为何要支持ipv6
苹果公司的App审核人员进行审核时,由于国内大部分开发者的服务器不支持IPv6-Only访问,因此只能通过苹果公司自己的NAT64+DNS64服务器进行测试,如果苹果的服务器不能有效的给AppServer返回一个IPv6地址,就会导致无法访问等问题。其结果便是审核失败,App被拒。
排查
目前发现部分手机出现网络请求慢问题(小米手机),但是一般手机都属于正常
于是使用以下代码 DNS 解析的 IP 地址
try {
InetAddress[] mInetAddresses= InetAddress.getAllByName("xxxx.cn");
for(InetAddress address: mInetAddresses) {
System.out.println(address.getHostAddress());
}
} catch (UnknownHostException e) { e.printStackTrace();}
发现
1、连接到公司wifi,只解析到 ipv4 地址
2、连接到4G网,解析到了ipv4、ipv6俩个地址
但是ipv6默认为集合中的第一个,是否我们可以尝试修改集合第一个为ipv4呢?
自定义okhttp中dns解析
查看了下okhttp开放了自定义dns方法,于是追踪到源码可以看到
package okhttp3;import java.net.InetAddress;import java.net.UnknownHostException;import java.util.Arrays;import java.util.List;/** * A domain name service that resolves IP addresses for host names. Most applications will use the * {@linkplain #SYSTEM system DNS service}, which is the default. Some applications may provide * their own implementation to use a different DNS server, to prefer IPv6 addresses, to prefer IPv4 * addresses, or to force a specific known IP address. * * <p>Implementations of this interface must be safe for concurrent use. */public interface Dns { /** * A DNS that uses {@link InetAddress#getAllByName} to ask the underlying operating system to * lookup IP addresses. Most custom {@link Dns} implementations should delegate to this instance. */ Dns SYSTEM = new Dns() { @Override public List<InetAddress> lookup(String hostname) throws UnknownHostException { if (hostname == null) throw new UnknownHostException("hostname == null"); try { return Arrays.asList(InetAddress.getAllByName(hostname)); } catch (NullPointerException e) { UnknownHostException unknownHostException = new UnknownHostException("Broken system behaviour for dns lookup of " + hostname); unknownHostException.initCause(e); throw unknownHostException; } } }; /** * Returns the IP addresses of {@code hostname}, in the order they will be attempted by OkHttp. If * a connection to an address fails, OkHttp will retry the connection with the next address until * either a connection is made, the set of IP addresses is exhausted, or a limit is exceeded. */ List<InetAddress> lookup(String hostname) throws UnknownHostException;}
于是我们去调换集合中ipv4 ipv6位置,将ipv4当到集合首位
import okhttp3.Dns;/** * File descripition: * * @author lp * @date 2019/4/16 */public class ApiDns implements Dns { @Override public List<InetAddress> lookup(String hostname) throws UnknownHostException { if (hostname == null) { throw new UnknownHostException("hostname == null"); } else { try { List<InetAddress> mInetAddressesList = new ArrayList<>(); InetAddress[] mInetAddresses = InetAddress.getAllByName(hostname); for (InetAddress address : mInetAddresses) { if (address instanceof Inet4Address) { mInetAddressesList.add(0, address); } else { mInetAddressesList.add(address); } } return mInetAddressesList; } catch (NullPointerException var4) { UnknownHostException unknownHostException = new UnknownHostException("Broken system behaviour"); unknownHostException.initCause(var4); throw unknownHostException; } } }}
将自定义方法插入到okhttp中
OkHttpClient.Builder httpClientBuilder = new OkHttpClient.Builder(); ClearableCookieJar cookieJar = new PersistentCookieJar(new SetCookieCache(), new SharedPrefsCookiePersistor(AppUMS.mContent)); httpClientBuilder .cookieJar(cookieJar) .addInterceptor(interceptor) .addInterceptor(new HeadUrlInterceptor()) //设置请求超时时长 .connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS) .writeTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS) .readTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS) .retryOnConnectionFailure(true)//错误重联 .dns(new ApiDns());
安装到以前访问慢的小米手机上,访问回归正常
最后补充
网上查到的解决办法说的是苹果审核阶段暂时开启ipv6,审核通过上线关闭ipv6,这样完全是可以的,但是治标不治本,如上操作就没必要一次一次修改了,本人测试红米6,大家有好的方法可以提出来共享下
最后给大家谋点福利,免费给大家下载csdn文件,留言邮箱即可,如邮箱:806875201@qq.com,地址:https://download.csdn.net/download/loocanp/10955164下载好之后发到留下的邮箱当中,2019.4.16开始 下载完积分为止作者:
网友评论