深入探索 Android 网络优化(三、网络优化篇)上

3)、双击 Breakpoints Settings 面板中的目标

URL,在弹出的 Edit Breakpoint 面板中进行编辑。

4)、这里默认选择断点 Request 与 Response,我们可以选择仅断点 Response 或 Request。点击确认即断点设置完成。
5)、然后,我们就可以点击主面板右侧的 Edit Response 编辑 Response,修改完成后点击最下方的 Execute 即可。
使用 Map Local
1)、自由模拟服务端的返回数据,以提前进行接口测试。
1)、右键点击要使用 Map Local 的 URL,选中Map Local 开启断点功能。
1)、然后,我们在 Edit Mapping 面板中选择 Map To 的 Local path,选择本地设定的 maplocal 本地数据(例如 JsonString)
弱网模拟功能
  • 1)、注意开启前需将 Map Local 关闭。

  • 2)、点击 Proxy => Throttle Setting => 选中 Enable Throttling

  • 3)、这里预设了很多模拟设置,我们只需将 网络包传输的速率 Throttle preset 设置为较低的速率(一般设为 256/512)。

碰到的问题

  • 1)、注意手机与笔记本电脑需要同一 WIFI 下,不能自己开热点或使用公司内网,否则无法在 电脑端 无法弹出手机连接 Charles 的提示确认框,并且也无法下载 Charles 提供的 SSL 证书。
  • 2)、手机端下载 Charles 提供的 SSL 证书时最好不使用系统浏览器访问。

3、Wireshark

强烈推荐 geektime-webprotocol

WireShark 主要可以用来对四种流进行跟踪,如下所示:

  • TCP
  • UDP
  • SSL
  • HTTP

1)、WireShark 基本使用

如何捕获报文
  • 1)、点击捕获->选项,打开捕获窗口
  • 网卡设备/流量/捕获过滤器,点击“开始”按钮开始抓包
  • 输出(指定缓存文件)/选项(显示、名称解析、自动停止抓包条件) 面板
  • 2)、点击捕获->停止,停止抓包

Wireshark 面板

快捷方式工具栏

数据包的颜色(视图->着色规则)

设定时间显示格式

数据包列表面板的标记符号

文件操作
  • 1)、标记报文 Ctrl+M。
  • 2)、导出标记报文(文件->导出特定分组),亦可按过滤器导出报文 ,
  • 3)、合并读入多个报文(文件->合并)。
如何快速抓取移动设备的报文?
  • 1、打开手机的 wifi 热点。
  • 2、电脑连接手机的 wifi 热点。
  • 3、用 Wireshark 打开捕获->选项面板,选择 wifi 热点对应的接口设备抓包即可。

2)、Wireshark 过滤器

如果表达式的背景为绿色,则说明过滤器的语法是正确的,红色则说明有错误。

捕获过滤器

它用于减少抓取的报文体积,使用 BPF(Berkeley Packet Filter) 语法,功能相对有限。

BPF 可以在设备驱动级别提供抓包过滤接口,多数抓包工具都支持此语法。而 BPF 的 Expression 表达式由多个 primitives 原语组成。而每一个 primitives 原语则由名称或数字,以及描述它的多个 qualifiers 限定词组成。

qualifiers 限定词
  • 1、Type:设置数字或者名称所指示类型
  • host、port。
  • net ,设定子网,net 192.168.0.0 mask 255.255.255.0 等价于 net 192.168.0.0/24。
  • portrange,设置端口范围,例如 portrange 6000-8000。
  • 2、Dir:设置网络出入方向
  • src、dst、src or dst、src and dst。
  • ra、ta、addr1、addr2、addr3、addr4(仅对 IEEE 802.11 Wireless LAN 有效)。
  • 3、Proto:指定协议类型
  • ether、fddi、tr、 wlan、
  • ip、 ip6、 arp、 rarp、
  • decnet、 tcp、udp、icmp、igmp、icmp
  • igrp、pim、ah、esp、vrrp
  • 4、其他
  • gateway:指明网关 IP 地址,等价于 ether host ehost and not host host。
  • broadcast:广播报文,例如 ether broadcast 或者 ip broadcast。
  • multicast:多播报文,例如 ip multicast 或者 ip6 multicast。
  • less, greater:小于或者大于。
简单示例

src or dst portrange 6000-8000 && tcp or ip6

显示过滤器

它对已经抓取到的报文进行过滤显示,功能强大。

基于协议域过滤
  • 捕获所有 TCP 中的 RST 报文:tcp[13]&4==4。
  • 抓取 HTTP GET 报文:port 80 and tcp[((tcp[12:1] & 0xf0) >> 2):4] = 0x47455420。(47455420 是 ASCII 码的 16 进制,表示”GET ”)
  • 抓取 HTTP POST 报文:port 80 and tcp[((tcp[12:1] & 0xf0) >> 2):4] = 0x504F5354
显示过滤器的过滤属性

任何在报文细节面板中解析出的字段名,都可以作为过滤属性。在视图->内部->支持的协议面板里,可以看到各字段名对应的属性名。例如,在报文细节面板中 TCP 协议头中的 Source Port,对应着过滤属性为 tcp.srcport。

常用操作符
  • 1)、and(&&):AND 逻辑与,ip.src==10.0.0.5 and tcp.flags.fin。
  • 2)、or(||):OR 逻辑或,ip.scr10.0.0.5 or ip.src192.1.1.1。
  • 3)、xor(^^):XOR 逻辑异或,tr.dst[0:3] == 0.6.29 xor tr.src[0:3] == 0.6.29。
  • 4)、not(!):NOT 逻辑非,not llc。
  • 5)、[…​]:中括号[]Slice 切片操作符
  • [n:m]表示 n 是起始偏移量,m 是切片长度,例如:eth.src[0:3] == 00:00:83
  • [n-m]表示 n 是起始偏移量,m 是截止偏移量,例如:eth.src[1-2] == 00:83
  • [:m]表示从开始处至 m 截止偏移量,例如:eth.src[:4] == 00:00:83:00
  • [m:]表示 m 是起始偏移量,至字段结尾,例如:eth.src[4:] == 20:20
  • [m]表示取偏移量 m 处的字节,例如:eth.src[2] == 83
  • [,]使用逗号分隔时,允许以上方式同时出现,例如:eth.src[0:3,1-2,:4,4:,2] ==00:00:83:00:83:00:00:83:00:20:20:83
  • 6)、in:大括号{}集合操作符,例如 tcp.port in {443 4430…4434} ,实际等价于 tcp.port == 443 || (tcp.port >= 4430 && tcp.port ⇐ 4434)。
可用函数
  • upper:将字符串字段转换为大写。
  • lower:将字符串字段转换为小写。
  • len:返回字符串或字节数组的字节长度。
  • count:返回在一帧中字段出现的数量。
  • string:将非字符串字段转换为字符串。
显示过滤器的可视化对话框

环形缓冲器

例如使用 3 个文件的环形缓存器,从 **.1 => **.2 => **.3 然后又从 **.1 文件开始记录,形成环形。

4、TcpDump(网络数据包嗅探器)

1)、抓包步骤

1、获取 ROOT 权限的手机一部
2、下载 tcpdump
3、将 tcpdump 安装到手机上

adb push tcpdump /data/local/tmp

4、修改 tcpdump 的权限,使其具有可执行的权限

chmod 777 /data/local/tmp/tcpdump

5、执行 tcpdump 命令进行抓包,按组合键 Ctrl + C 可以停止抓包
6、将抓到的数据包的信息保存为 Pcap 文件,这里仅需在执行 tcpdump 后加上 -w 参数

tcpdump-w /data/local/tmp/tcp.pcap

7、把 Pcap 复制到 电脑上,使用 Wireshark 分析数据包的流量。

2)、捕获及停止条件

  • -D:列举所有网卡设备。
  • -i:选择网卡设备。
  • -c:抓取多少条报文。
  • –time-stamp-precision:指定捕获时的时间精度,默认毫秒 micro,可选纳秒 nano。
  • -s:指定每条报文的最大字节数,默认 262144 字节。

3)、文件操作

  • -w:输出结果至文件(可被Wireshark读取分析)。
  • -C:限制输入文件的大小,超出后以后缀加 1 等数字的形式递增。 注意单位是 1,000,000 字节。
  • -W:指定输出文件的最大数量,到达后会重新覆写第 1 个文件。
  • -G:指定每隔N秒就重新输出至新文件,注意-w 参数应基于

strftime 参数指定文件名。

  • -r:读取一个抓包文件。
  • -V:将待读取的多个文件名写入一个文件中,通过读取该文件同时 读取多个文件。

4)、输出时间戳格式

  • -t:不显示时间戳。
  • -tt:自1970年1月1日0点至今的秒数。
  • -ttt:显示邻近两行报文间经过的秒数。
  • -tttt:带日期的完整时间。
  • -ttttt:自第一个抓取的报文起经历的秒数。

5)、分析信息详情

  • -e:显示数据链路层头部。
  • -q:不显示传输层信息。
  • -v:显示网络层头部更多的信息,如 TTL、id 等。
  • -n:显示 IP 地址、数字端口代替 hostname 等。
  • -S:TCP 信息以绝对序列号替代相对序列号。
  • -A:以 ASCII 方式显示报文内容,适用 HTTP 分析。
  • -x:以 16 进制方式显示报文内容,不显示数据链路层。
  • -xx:以 16 进制方式显示报文内容,显示数据链路层。
  • -X:同时以 16 进制及 ACII 方式显示报文内容,不显示数据链路层 • -XX 同时以 16 进制及 ACII 方式显示报文内容,显示数据链路层。

5、Stetho

  • 1)、在 build.gradle 中,除了 Stetho 依赖外,还需添加 ‘com.facebook.stetho:stetho-okhttp3:1.5.0’。
  • 2)、在 Application 的 onCreate 方法中初始化 ‘Stetho.initializeWithDefaults(this)’。
  • 3)、调用 OkHttp 的 ‘addNeworkInterceptor’ 方法添加 Stetho 用于收集网络信息而提供的网络拦截器。
  • 4)、访问 Chrome 调试页面 ‘chrome://inspect’。

6、其它的性能检测工具

  • strace:跟踪 Socket 相关的系统调用。
  • netstat:记录多种网络栈和接口统计信息。
  • ifconfig:记录接口配置。
  • ip:记录网络接口统计信息。
  • ping:测试网络连通性。
  • traceroute:测试网络路由。
  • /proc/net 命令:查看网络统计信息,Android TrafficState 使用了 /proc/net/xt_qtaguid/stats 和 /proc/net/xt_qtaguid/iface_stat_fmt 文件来统计 App 的流量信息。

三、精准获取流量消耗

1、如何判断 App 流量消耗偏高?

  • 1)、绝对值看不出高低。
  • 2)、对比竞品,相同 Case 对比流浪消耗。
  • 3)、异常监控超过正常指标。

2、测试方案

  • 1)、打开手机设置 => 流量管理 => 仅允许目标 App 联网
  • 2)、可以查找出大多数的问题,但是线上场景线下可能遇不到。

3、线上流量获取方案

1)、TrafficStats

特点
  • API 18 以上。
  • 记录手机重启以来的数据流量。
API
  • getMobileRxBytes():通过蜂窝流量接收到的信息。
  • getUidRxBytes(int uid):获取指定 uid 的接收流量。
  • getTotalRxBytes():总发送流量。
缺点

无法获取某个时间段内的流量消耗。

2)、NetworkStatsManager

API 23 之后。

特点
  • 1)、获取指定时间间隔内的流量信息。
  • 2)、获取不同网络类型下的消耗。
NetUtils.getStats

获取指定时间间隔的 蜂窝 + WIFI 流量总信息

4、前后台流量获取方案

问题:线上反馈 App 后天流量消耗大?

只获取一个时间段的流量不够全面。

实现原理

后台定时任务 => 获取时间间隔内流量 => 记录前后台 => 分别计算 => 上报 APM 后台 => 流量治理依据

小结

  • 1)、该方案无法获取应用在前后台切换时的流量,因此有一定的误差,但这个误差是可以接受的。
  • 2)、结合精细化的流量异常报警针对性的解决后台跑流量的问题。

成功 log 如下所示:

2020-05-11 10:47:55.633 4036-4181/json.chao.com.wanandroid I/WanAndroid-LOG: │ [MainActivity.java | 193 | lambda$initEventAndData 1 1 1MainActivity] backNetUseData: 4 MB
2020-05-11 10:47:55.646 4036-4181/json.chao.com.wanandroid I/WanAndroid-LOG: │ [MainActivity.java | 194 | lambda$initEventAndData 1 1 1MainActivity] foreNetUseData: 4 MB
2020-05-11 10:47:55.652 4036-4181/json.chao.com.wanandroid I/WanAndroid-LOG: │ [MainActivity.java | 197 | lambda$initEventAndData 1 1 1MainActivity] totalNetUseData: 8 MB

四、网络请求流量优化

1、常见使用网络的场景

1)、数据压缩

POST 请求 Body 使用 GZip 压缩,同时服务端返回 Body 也使用 GZip 压缩。

2)、图片

  • 图片上传前压缩。
  • 图片使用策略细化:让 服务端/CDN 云服务器 优先使用缩略图/WebP格式图片。

3)、性能日志上报:批量 + 特定场景上报

APM 相关、单点问题相关。例如埋点数据可以等到某一时机点(例如 开启了 WIFI、数据量过大必须上传一部分时)再上传。

4)、数据缓存

服务端返回加上过期时间,避免每次重新获取。 节约流量且大幅提高数据访问速度,更好的用户体验。

Request 缓存设置
  • 1、Pragma:no-cache:去服务器拉取最新的资源,不使用缓存。
  • 2、If-Modified-Since:datetime:如果资源在客户端提供的时间后发生改变,服务器会返回新的资源,否则使用缓存。
  • 3、If-None-Match:etagvalue:如果资源的标识和服务器的不同,返回新的资源。

当 Request 的头部是 2 和 3 时,如果服务器的资源没有修改,则服务器会返回 HTTP/304 Not Modified,客户端会使用缓存的 Response。

Response 缓存设置

HTTP Response 是否可以缓存是由 Response 的头部控制的,服务器可以通过 Expires 和 Cache-Control 控制 Response 如何在客户端缓存。

Expires

Expires 头部会包含一个日期,即该资源缓存的有效期,客户端有新的相同请求时,如果资源缓存没有过期,则使用缓存资源,服务器不会返回任何东西。

Cache-Control

Cache-Control 可以标明 Response 如何存储及其如何使用,其选项如下所示:

  • 1)、public:Response 可以存储在任何 Cache 中,包括共享的 Cache。
  • 2)、private:Response 存储在私有 Cache 中,只能被一个用户使用。
  • 3)、no-cache:Response 将来不会被使用。
  • 4)、no-store:Response 将来不会被使用,也不会写到磁盘上。
  • 5)、max-age=#seconds:Response 在设定的时间内可以被重复使用。
  • 6)、must-revalidate:和原始服务器确认 Response 是最新后,可以使用缓存。
OKHttp 无网数据缓存实现

POST 在 OKHttp 中默认不会缓存,因为 POST 一般是用来修改数据的。在 Awesome-WanAndroid 中的 HttpModule—cacheInterceptor 中就已经实现了 OKHttp 的无网数据缓存,代码如下所示:

File cacheFile = new File(Constants.PATH_CACHE);
Cache cache = new Cache(cacheFile, 1024 * 1024 * 50);
Interceptor cacheInterceptor = chain -> {
Request request = chain.request();
if (!CommonUtils.isNetworkConnected()) {
// 无网时强制使用数据缓存,以提升用户体验。
request = request.newBuilder()
.cacheControl(CacheControl.FORCE_CACHE)
.build();
}
Response response = chain.proceed(request);
if (CommonUtils.isNetworkConnected()) {
int maxAge = 0;
// 有网络时, 不缓存, 最大保存时长为0
response.newBuilder()
.header(“Cache-Control”, “public, max-age=” + maxAge)
.removeHeader(“Pragma”)
.build();
} else {
// 无网络时,设置超时为4周
int maxStale = 60 * 60 * 24 * 28;
response.newBuilder()
.header(“Cache-Control”, “public, only-if-cached, max-stale=” + maxStale)
.removeHeader(“Pragma”)
.build();
}
return response;
};
// 缓存优化
builder.addNetworkInterceptor(cacheInterceptor);
builder.addInterceptor(cacheInterceptor);
builder.cache(cache);

5)、离线包、增量数据更新

加上版本的概念,仅传输有变化的数据。

总结

最后为了帮助大家深刻理解Android相关知识点的原理以及面试相关知识,这里放上相关的我搜集整理的Android开发中高级必知必会核心笔记,共计2968页PDF、58w字,囊括Android开发648个知识点,我把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包知识脉络 + 诸多细节。

网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。希望这份系统化的技术体系对大家有一个方向参考。

2021年虽然路途坎坷,都在说Android要没落,但是,不要慌,做自己的计划,学自己的习,竞争无处不在,每个行业都是如此。相信自己,没有做不到的,只有想不到的。

虽然面试失败了,但我也不会放弃入职字节跳动的决心的!建议大家面试之前都要有充分的准备,顺顺利利的拿到自己心仪的offer。

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

止,不再深入研究,那么很难做到真正的技术提升。希望这份系统化的技术体系对大家有一个方向参考。

2021年虽然路途坎坷,都在说Android要没落,但是,不要慌,做自己的计划,学自己的习,竞争无处不在,每个行业都是如此。相信自己,没有做不到的,只有想不到的。

虽然面试失败了,但我也不会放弃入职字节跳动的决心的!建议大家面试之前都要有充分的准备,顺顺利利的拿到自己心仪的offer。

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 9
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值