暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

ipv6-来自移动网络的全新挑战

轻易科技技术中心 2018-09-25
1626

写在前面

 上线遇到问题不可怕,关键是要有解决问题的思路。要大胆猜测问题产生的原因,同时静下心来通过做实验的方式验证自己的猜想。解决问题的过程就是自我成长的过程。

       这篇文章产生的背景,来自于一次app生产上线,从焦头烂额到问题完美解决,期间经历了无数坎坷,最终总结出了这篇血与泪的教训,让我们的故事正式开始吧~


0-生产冒烟的非必现bug

        2018年5月16日,经过开发、测试、产品验收,3.5.5版本终于上线了。

        “请求不到数据,特别慢,用的4g”,语气中带些焦躁。

        “没事啊,我的都正常,内网外网都可以,是你手机出问题了吧”

        “我的是先开始慢,然后就快了”

        “我的也是”

        ......

        混乱的状态没持续多久,问题调差行动就正式开始了。


1-问题出在了哪?

难的,莫过于定位问题。很多时候,找出了问题所在,问题已经解决了一大半。对于这种有的手机好,有的手机不行的问题,最让人头疼。我们能做的,就是收集大量和问题有关的信息,找规律。

梳理现象

  1. 3.5.5版本,部分机型使用移动4g网络访问,访问接口,速度异常缓慢(10s左右),但是过后会变快。h5正常

  2. 更换手机apn,访问速度会变快

  3. 同一台手机,更换手机卡,访问速度非常快

  4. 同一个手机卡,换到别的手机,访问速度非常快


问题猜想

问题无非可以分为两大类,服务器或客户端。

客户端可能存在的问题:

1.1 网络请求工具httpurlconnection 

1.2 网络框架volley    

1.3 编译版本     

1.4 机型    

 

服务器可能存在的问题:

1.5 公司服务器网络处理    

1.6 公司服务器移动网络层问题    


逐一排查

1.1 网络请求工具HttpURLConnection

猜想:请求过多?  证书校验 ? 

1.1.1 单一网络请求

由于app内有大量网络请求,为了防止其他请求干扰结果,改动app,在欢迎页面请求接口,挑选在真实情况中发生请求慢的情况的接口,只请求一个接口一次,发现速度很慢。

说明:网络请求慢和多次请求没有关系

1.1.1 HttpURLConnection请求

请求序列

响应时间

1

10s

2

1s

3

1s

4

1s

5

1s

1.1.2 使用OkHttp:OkHttp POST请求:

请求序列

响应时间

1

10s

2

1s

3

1s

4

1s

5

1s

说明,网络请求慢和网络库没有直接关系

1.2 Volley网络框架

猜想:如果volley框架有问题,那么:

a 不用volley请求,如果请求依然很慢,则说明volley可能没问题;

b 如果替换volley中的HttpURLConnection,请求依然很慢,则说明Volley本身没有问题,是链接网络的类库出现问题

因为1.1中已经证明,HttpURLConnection请求第一次会很慢,因此a是正确的,说明volley可能没问题,接下来证明b:

使用OkHttp替换Volley中的HttpUrlconnection,app第一次请求仍然10s

说明:Volley框架是没有影响的


1.3 编译版本

调整编译版本,多次重复上述实验,无影响。

说明:编译版本无问题

1.4 机型

实验当天:小米、锤子、OPPO、三星S8、华为P6均有问题

说明:机型无影响

1.5 公司服务器网络处理

猜想,问题产生当天,同事说其他app快的飞起,那说明别人家的务器肯定没问题,挑选宜人贷做对比实验:

测试组合

响应时间(3次求均值)

http://www.me.com

10s

https://www.yirendai.com

2s以内

由此确定:公司服务器所处网络、公司服务器处理肯定存在问题

1.6 公司服务器移动网络层问题

1.6.1 cient发送http请求后,到底什么时候才开始tcp链接?

请求发出后,tcp链接一直没有建立。在请求发出的这10s秒钟,到底发生了什么呢?为什么过了这么久才开始建立tcp链接?

1.6.2 分析http请求源码

通过查阅资料,发现Okhttp底层处理tcp链接的类为AndroidPlatform.class,打断点进入:

惊奇发现,socket建立的链接地址,居然不是公司的ipv4服务器,而是一个ipv6地址!更为惊奇的是,socket链接超时链接时间恰巧为10s!

让断点执行完毕。

等待10s后,断点再次进入!

这次进来的是socket链接ip为公司ipv4地址,说明ipv6建立tcp链接超时,重试另一个ip,请求瞬间成功。

抓包分析现象:

发现,DNS服务器先后返回了2个域名!  第一次是有问题的的ipv6地址,第二次是正确的公司域名,因此确定问题所在

使用wifi环境,发现域名完全正确,更加说明了是DNS服务器的问题


2-如何解决

1 服务器在DNS中去掉ipv6的域名

2 Android客户端,自定义DNS解析,过滤掉ipv6

3 购买httpDNS

根据自己的情况,以上方法任选


3-那些让我们困惑的点

3.1 为什么只有移动有问题

电信抓包:

联通抓包:

wifi抓包:

实验证明,电信、联通、wifi,都只请求了一次dns

只请求一次的深层次原因,在3.2中解答。

3.2 网络框架为啥发起了两次DNS请求

android dns 请求流程图如下:

java中调用

最终调用的方法是bionic库中的getaddr:https://android.googlesource.com/platform/bionic/+/master/libc/dns/net/getaddrinfo.c

我们看到,ai_family是java传过来的,对应AF_UNSPEC。通过分析代码,首先判断ipv6、ipv4是否可用,然后会先后配置ipv6、ipv4的请求。

判断ipv6、ipv4是否可用的方法为_have_ipv6和_have_ipv4,方法描述写的非常清楚:

The following functions determine whether IPv4 or IPv6 connectivity is available

通过代码分析得知:移动网络之所以请求两次DNS,是因为ipv6网络可用

为了验证上述说法,使用ifconfig命令,分别查看手机上插入移动、联通、电信手机卡的网络情况

移动卡:


联通卡:

电信卡

wifi:

发现:只有移动网络的ipv6是可用的,拥有公网可访问2000开头的ip,其他机型只有fe80开头的local ip,验证了以上猜想

3.3 Ipv 6可用,为啥会超时

3.3.1 使用ipv6test

发现https://www.me.com的AAAA DNS没问题,但是webserver不同

测试ipv6.google.com

 3.3.2 验证公司服务器

在digitalocean上申请一台支持ipv6的Droplet(选择digitalocean做实验平台,是因为digitalocean支持ipv6)

可以解析到ipv6.google.com

ping6可以ping通服务器

curl也可以取到数据,证明这台服务器支持ipv6

然后测试公司提供的ipv6

事实证明,公司域名拥有ipv6地址,但是ipv6地址不可以访问.

备注:公司拥有ipv6地址的原因是符合AppStore审核规则

3.4 为什么更改apn为wap以后,链接速度变快了

因为换成wap的apn之后,socket可以通过wap的代理,直接建立链接


4-总结与收获

1 遇到网络问题,可以从socket层代码进行分析

2 多了解android底层代码,可能日常开发过程中使用的机会很少,但是可以为以后解决疑难问题打下基础

3 ipv6国情:整体ipv6覆盖率非常非常低,主要的ipv6网络是教育网,商用ipv6几乎为0。通过做实验,发现移动、联通、电信三大运营商,只有移动支持ipv6



文章转载自轻易科技技术中心,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论