Android 网络性能优化(4)弱网优化,2021春招BAT面试真题详解

  1. throughput

吞吐量,它是用来衡量单位时间内成功传送数据的数量,是比较权威的、官方的衡量网络质量的指标。最简单的公式: 吞吐量 = C / T ,C为完成的任务总量,T为完成这些任务的时间。

  1. singal strength

指的是无线信号强度,也就是我们的wifi信号格。Android上SDK就可以支持获取了,而iOS则需要通过黑科技来获取。

  1. bandwidth-delay product(带宽时延乘积)

带宽时延乘积,指的是一个数据链路的能力(bit/s)与来回通信延迟(s)的乘积。其结果是以比特(或字节)为单位的一个数据总量,反映的是当前网络通道的最大容量。Tcp中有滑动窗口的概念,会限制发送和接收数据的大小,所以Tcp窗口的大小是直接受带宽时延乘积的影响,来设置接收缓冲区大小和发送缓冲区大小。

2.3 建立弱网标准 / 弱网检测


在 百度APP移动端网络深度优化实践分享(三):移动端弱网优化篇中,百度使用的是一个循序渐进的过程,通过三个阶段来建立一个弱网标准:

  1. 第一阶段,线下测试

获取预期的阈值,在测试App网络切换、DNS故障时,抓取这些数据

  1. 第二阶段,线上进行验证

通过线下获取到的阈值,在线上可以获取到弱网的比例,找到会出现弱网的场景,进行诊断优化。(比如网络体验最好的微信,也只是在信令的传输上优化到极致)

  1. 第三阶段,线上反复试验

通过反复试验来调整阈值,使得优化更接近业务层。

腾讯的做法也大同小异,都是根据2.2的指标进行数据收集,整理一套达到弱网时的数据标准。但是我们该如何去探测这些数据呢?这需要我们实现一套完整的网络探测架构。

3. 弱网检测

=========================================================================

这部分基本照抄百度的实现了。网络探测是弱网检测的基础,目标是能够即时、正确的检测出网络质量,我们把网络探测分成两个部分,主动网络探测被动网络采集

3.1 主动网络探测


主动检测,就是在触发了某些特定条件后,主动的进行网络检测,并按照一定的条件检查出是否为弱网状态。架构图如下所示:

在这里插入图片描述

3.1.1 策略层

策略层,通过多种策略,使主动探测的即时性和准确性得到提高。主要在网络请求成功和失败的时候触发弱网检测的逻辑。大致分成下面三个逻辑:

  1. 成功时,如何判断进入弱网状态?

检测 httprtt,是否达到弱网的阈值(即设定的 weak-httprtt),大于这个值就会进入弱网检测,为了防止频繁触发探测,加了时间间隔,一般为5~15min

  1. 成功时,如何判断退出弱网状态?

检测 httprtt,是否没有达到阈值(即设定的 good-httprtt),如果小于这个值则切回到正常的网络状态。防止频繁触发探测,加了时间间隔,一般为30s~60s。

在多次实验中,发现如果小于阈值,就一定是正常状态,而大于或等于阈值,并不能证明一定不是正常网络,所以也需要发起网络探测。但是由于这个动作是发生在成功的回调里,所以频次会很高,所以需要加上时间间隔。可能还需要限制次数。

  1. 失败时,如何判断进入弱网状态?

直接进行网络探测,但是由于可能会频繁触发,其检测的条件需要比成功时检测要更加严苛,所以不会在时间上加限制,而是从次数上加限制。

进入网络探测状态后,就轮到基础能力层来实现。

3.1.2 基础能力层

基础能力层就是提供网络探测的手段,一般有两个:

  1. dns query

使用Android系统的默认DNS服务器来查询目标服务器的(核心)域名,DNS查询的超时时间为3s

  1. ping

正所谓“想测网络通不通,不ping百度ping京东”。因为他们的服务器都比较稳定,很少宕机,通过ping这些域名来了解当前网络状态、丢包率等信息。ping的次数为两次,超时时间默认是1s。

为什么要使用这两种手段呢?这是因为网络请求的过程中,主要有 DNS查询、TLS握手、TCP握手。而 DNS Query可以用来获取dns是否出现问题,ping可以用来检测TCP连接的连通性。

除了上面两种手段,应该也有其他网络探测的方式。在执行完这些手段后,将探测数据交给接口层。

3.1.3 接口层

接口层提供网络状态,大致为下面几个:

  • GOOD

DNS查询成功、Ping成功,且没有超时、无丢包

  • BAD

ping失败则为BAD

  • UNKNOWN

无法识别状态

  • OFFLINE

dns查询错误、网关错误,发送dns错误、ping读写错误、接收dns错误、ping地址错误等

3.2 被动网络采集


被动采集,就是每一次网络请求的所有细节都进行记录,并按照一定的条件将原始信息进行上报,上层再根据条件判断是否是弱网状态。cronet(Chromium提供给Android的网络堆栈库)可以提供这个能力,OkHttp应该没有这种能力,所以可以考虑接入 cronet。

被动采集的信息主要有以下三个:

  1. tcprtt

  2. httprtt

  3. throughput

架构图如下所示:

Android 网络性能优化(4)弱网优化,2021春招BAT面试真题详解_第1张图片

3.2.1 基础能力层

基础能力层就是采集网络请求的三个参数tcprtt、httprtt、throughput。

(1)tcprtt采集

基于posix和windows的socket编程接口来获取tcprtt。获取时机在连接完成,读完成和写完成;

(2)httprtt采集

基于HTTP协议栈实现,通过计算接收response数据开始和开始发送的时间差,来获取httprtt。获取时机在读首包完成时;

(3)throughput采集

通过计算公式获取bytes总量和时间,基于posix和windows的socket编程接口来获取bytes。获取时机在读完成时记录接收的bytes,在写完成时记录发送的bytes。时间的获取在吞吐量管理模块里完成,获取时机在请求完成和请求销毁时。

3.2.2 策略层

通过获取到的数据进行上报,三种数据对应三种模块,对于上报的时机需要做处理。

(1) 套接字管理模块

使用cronet的话,可以通过 getsockopt()函数获取 tcp_info结构体中的 trcpi_rtt值。其次由于tcprtt的上报比较频繁,所以需要做时间限制,最少间隔 1~3s

(2)吞吐量管理模块

负责吞吐量计算,之前介绍了公式,从网络活动监控器模块获取bytes,但是吞吐量的计算单位是bits,所以将bytes乘以8,。只有GET请求会被列入统计计算,并且至少要累计5个请求才开始统计计算。

排除精准度的干扰,比如 localhost,私有子网上的主机,特定用途的子网主机,可以参考 rfc1918 的规范

(3)网络质量管理模块

从套接字管理模块获取tcprtt,从吞吐量管理模块获取吞吐量,并且在Http协议栈读到首包完成时获取httprtt。

获取到这三个值后,需要经过一些策略限制上报的频次,10s的间隔限制;网络类型不能是UNKNOWN;网络不能频繁切换;rtt和总吞吐量大小各300。

这些限制都是为了排除误差、降低性能损耗。

3.2.3 接口层

接口层提供的状态是对标主动采集的网络状态的,所以也包括 GOOD、BAD、UNKNOWN、OFFLINE

  1. GOOD

3G网、4G网、5G网,任一条件满足即标记为GOOD状态。

通过阈值标记3G和广义的4G,httprtt大于等于273ms,tcprtt大于等于204ms,即标记为3G状态。

小于这两个值则被标记为4G、5G网。

  1. BAD

2G网、httprtt大于1.31s,任一条件满足则标记为BAD状态。阈值需要在网上查询资料,根据业务线调整。

  1. UNKNOWN

非法的httprtt、tcprtt、吞吐量,任一条件满足则标记为UNKNOWN状态。比如初始化的时候,有的值会标为-1

  1. OFFLINE

依赖平台能力进行判断,Android可以利用 ConnectivityManager得到 NetworkInfo,判断网络信息(没有连接wifi、或者wifi无网络等)

4. 弱网状态下的优化

=============================================================================

4.1 使用QUIC进行弱网优化


QUIC是一种udp协议,由google发明,实现了TCP+TLS+HTTP/2,它还有一个更加响亮的名称: Http/3,Cronet库对其进行了支持,Android、iOS平台都可以使用。因为我自身对QUIC并不了解,所以这里并不会给出过多的使用介绍,接下来的一个月内,我会专门学习并写一篇有关 QUIC的文章。

总的来说,QUIC协议本身高效节流的特性,使得它在弱网络环境下可以大施拳脚。那么如何使用它呢?

4.1.1 网络库切换

在进行网络探测,并根据探测结果诊断当前网络状态为弱网时,网络请求进行切换,即将请求库切换到QUIC。

而当网络探测恢复为正常状态时,使用正常的网络库,例如OkHttp。

4.1.2 QUIC预连接

所谓QUIC的预连接,就是在进入弱网状态前提前建立QUIC连接。QUIC有引以为傲的0RTT,但第一次建立连接的时候是需要1RTT的,客户端首先会向服务器发送一个client hello消息,服务器会回复一个server reject消息,这个消息中包括了server config,有了server config后客户端就可以直接计算出密钥,完成0RTT。

所以我们在App启动的过程中会做一次QUIC预连接,将server config拉取下来,这样等进入弱网后走QUIC协议。

4.2 复合连接


复合连接,即多条连接。它解决的场景是为了多个IP地址的连接选取问题。无论是HttpDNS还是LocalDNS中,我们都能获取到一个域名下的多个ip。我们可以找到最优ip进行连接:

比如我们通过HttpDNS获取到两个ip,那我们将走下面步骤:

  1. 如果结果中存在IPv6的地址,那么

《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》

【docs.qq.com/doc/DSkNLaERkbnFoS0ZF】 完整内容开源分享

会优先选用IPv6的地址,这个规则follow HappyEyeBall机制(可参考系列一对于HappyEyeBall的介绍)

  1. 接下来这两个IP会按照顺序尝试建立连接,如果第一个IP返回失败,将立即开始连接第二个IP

  2. 如果第一个IP率先成功返回,那么第二个IP将被加入连接尝试列表并停止所有尝试连接

  3. 如果第一个IP失败,会立刻开始第二个IP的连接

  4. 如果第一个IP处于pending状态,那么会启动一个定时器,默认延迟2s会发起第二个IP的连接,如果是多个IP将会递归连接,需要特别说明下,不同的网络制式延迟时间会不一样,这样体验也会更好。

复合连接的好处是提供最优的ip选取机制,但是也会带来服务端的高负载,所以使用的时候需要进行综合评估。

4.3 其他


  • 减少资源传送

  • 重连

  • 合并资源请求

  • 使用缓存兜底

  • 心理博弈,在ui层面上让用户耐心等待

5. 弱网测试

=========================================================================

弱网测试的本质是模拟弱网环境。通过 Fiddler可以模拟。这里我介绍一种更便捷的方式: QNET

QNET弱网测试由腾讯开发,无需ROOT手机,无需连接数据线,以独立app的方式,为用户提供给快捷、可靠、功能完善的弱网络模拟服务,下载地址:QNET弱网测试

先选择需要测试的App:

Android 网络性能优化(4)弱网优化,2021春招BAT面试真题详解_第2张图片

然后设置参数,QNET提供了多个参数调整:

Android 网络性能优化(4)弱网优化,2021春招BAT面试真题详解_第3张图片

最后可以查看弱网模板:

Android 网络性能优化(4)弱网优化,2021春招BAT面试真题详解_第4张图片

6. 参考文章

你可能感兴趣的:(程序员,面试,android,移动开发)