【转】流量都去哪儿了 —— 三板斧搞定Android网络流量测试
转自:http://www.10tiao.com/html/179/201605/2652313673/1.html
流量是什么?
为什么要进行流量测试?
流量测试方法有哪些?
怎么统计流量并进行结果分析?
带着这些疑问,小编带您探寻Android网络流量的测试方法。
1 流量是什么?
随着智能手机的普及,移动互联网日新月异。人们在享受移动互联网带来的方便的同时,也需要向网络运营商支付昂贵的“流量”费用(在移动网络下)。下图的流量提醒的短信大家应该很熟悉:
事实上,这些流量都是手机里的应用在进行网络通信时所产生。很多流量工具都能帮我们统计各个应用所消耗的流量。下图为小米系统“安全中心”网络助手统计到的流量消耗情况:
根据维基百科的解释,网络流量是指能够连接网络的设备在网络上所产生的数据流量。流量有用户层面、网站层面、管理层面、综合层面等四个不同层面的意义。这里主要讨论用户层面的意义,也就是移动终端侧产生的流量。
2 为什么要进行流量测试?
随着3G、4G时代的来临,移动网络速度越来越快,流量资费也越来越便宜。但时至今日,流量资费对很多用户来说依然很昂贵。每个月的流量套餐依然不够用。一个应用是否费流量可能影响到用户的使用频率甚至决定用户是否继续使用。
流量测试可以通过测量应用在特定使用场景下所产生的流量,从而发现异常流量和改进点。促使应用节省流量。
除节省流量之外,流量优化还能间接产生如下效果:
(1)提高用户体验(打开页面更快了)
(2)减轻服务器压力
3 流量的不同统计维度
网络传输遵循TCP/IP协议。应用层的数据要经过TCP层、IP层和以太网接口层的层层包装才能在物理链路中传输。因此,应用程序要通过网络传输数据时,数据被送入协议栈中,然后逐个通过每一层直到被当作一串比特流送入网络。其中每一层对收到的数据都要增加一些首部信息(有时还要增加尾部信息),TCP传给IP的数据单元称作TCP消息段或简称为TCP段(TCP segment)。IP传给网络接口层的数据单元称作IP数据报(IPDatagram)。通过以太网传输的比特流称作帧(Frame)。如下图所示。
所以你在不同的地方看到同一个数据包统计出来的流量不同时,通常都是因为它们统计的维度不同。
4 Android系统流量测试方法
流量测试的工具和方法有很多。根据实现原理大致可归类为以下3种:
【方法1】Tcpdump抓包 +wireshark分析
【方法2】读取Linux流量统计文件
【方法3】利用android流量统计api
下面分别介绍这3种方法:
【方法1】Tcpdump抓包 +wireshark分析
第一步:tcpdump抓包
(1)手机要有root权限
(2)下载tcpdump http://www.strazzere.com/android/tcpdump
(3)adb push c:\wherever_you_put\tcpdump /data/local/tcpdump
(4)adb shell chmod 6755 /data/local/tcpdump
(5)adb shell,su获得root权限
(6)cd /data/local
(7)/tcpdump -p -vv -s 0-w /sdcard/capture.pcap
(8)adb pull/sdcard/capture.pcap d:/
命令参数说明:
(更多参数说明参考:http://www.cnblogs.com/ggjucheng/archive/2012/01/14/2322659.html)
(1)-p: 一般情况下, 把网络接口设置为非'混杂'模式.
(2)–vv: 产生比-v更详细的输出.
(3)-s 0 : 抓取数据包时默认抓取长度为68字节。加上-S 0 后可以抓到完整的数据包
(4)-w ./target.cap : 保存成cap文件,方便用ethereal(即wireshark)分析
(5)tcp: ip icmp arp rarp 和 tcp、udp、icmp这些选项等都要放到第一个参数的位置,用来过滤数据报的类型(6)-i eth1 : 只抓经过接口eth1的包
(7)-t : 不显示时间戳
(8)-c 100 : 只抓取100个数据包
(9)dst port ! 22 : 不抓取目标端口是22的数据包
(10)src net 192.168.1.0/24 : 数据包的源网络地址为192.168.1.0/24
这里会有一个疑问,为什么有时抓包为0?
答:因为网络接口不对。不同的手机可能使用不同的网络接口进行通信。
Tcpdump命令有-i interface参数,指定tcpdump 需要监听的接口. 如果没有指定, tcpdump 会从系统接口列表中搜寻编号最小的已配置好的接口(不包括 loopback 接口)。一但找到第一个符合条件的接口, 搜寻马上结束。
在采用2.2版本或之后版本内核的Linux 操作系统上, 'any' 这个虚拟网络接口可被用来接收所有网络接口上的数据包(nt: 这会包括目的是该网络接口的, 也包括目的不是该网络接口的). 需要注意的是如果真实网络接口不能工作在'混杂'模式(promiscuous)下,则无法在'any'这个虚拟的网络接口上抓取其数据包。所以你如果使用
./tcpdump -p -vv -s 0 -w /sdcard/capture.pcap
抓包为0,你可以试一下
./tcpdump -i any -p -s 0 -w /sdcard/capture.pcap
如果依然不行,则需要查看一下手机使用的是哪个网络接口。方法如下:
(1)adb shell,su获得root权限
(2)cat /proc/net/dev
如上图: lo 为本地流量, rmnet0为移动网络流量, wlan0 为wifi流量.所以如果我们抓移动网络的包,命令应改为:
./tcpdump -i rmnet0 -p -s 0 -w /sdcard/capture.pcap
第二步:wireshark统计流量
wireshark打开刚刚的抓包文件,使用filter做过滤,根据wireshark显示过滤器的语法,假设APP对应的目标服务器的地址是(121.14.76.22)
Filter的语法:
“入流量” ip.src == 121.14.76.22
“出流量” ip.dst == 121.14.76.22
那么怎么统计这些过滤出来的包的大小呢?statistics下面有一个summary
我们要的数据就在这里
我们要的入流量的数据就是红框里面的数值。
Wireshark的基础操作请参考:
http://www.cnblogs.com/tankxiao/archive/2012/10/10/2711777.html
【方法2】读取Linux流量统计文件
Linux系统有3个地方保存流量统计文件:
(1)在/proc/net/dev下可以查看各个网络接口的收发流量
(2)在/sys/class/net/下可以找到相关类别(如rmnet0)的目录.在其子目录statistics下游rxbytes和txbytes记录收发流量.
(3)在/proc/uid_stat/{uid}/tcp_rcv记录该uid应用下载流量字节,/proc/uid_stat/{uid}/tcp_snd有该uid应用上传流量字节
3个地方统计的流量异同点如下:
统计数据出处 |
是否区分网络接口 |
是否区分app |
说明 |
/proc/net/dev |
是 |
否 |
区分本地流量、无线网络流量、wifi流量。 统计整个系统的流量。 |
/sys/class/net/ |
是 |
否 |
区分本地流量、无线网络流量、wifi流量。 统计整个系统的流量。 |
/proc/uid_stat/{uid} |
否 |
是 |
根据uid区分app流量。 统计该app的所有流量。 |
/proc/net/dev输出内容:
/proc/uid_stat/{uid}/tcp_rcv操作方法:
(1)Adb shell进入手机之后,执行ps
Uid的值就是在63+10000=10063 ,即在要统计的APP后面的数据上加上10000
(2) Cat 这个文件即可,单位是byte。
【方法3】利用Android流量统计API
对于Android流量统计来说在2.2版中新加入了TrafficStats类可以轻松获取,其实本身TrafficStats类也是读取Linux提供的文件对象系统类型的文本(方法2中提到的3种文件)进行解析。android.net.TrafficStats类中,提供了多种静态方法,可以直接调用获取,返回类型均为 long型,如果返回等于-1代表 UNSUPPORTED 当前设备不支持统计。其主要的方法:
static long getMobileRxBytes()//获取通过Mobile连接收到的字节总数,但不包含WiFi
static long getMobileRxPackets()//获取Mobile连接收到的数据包总数
static long getMobileTxBytes()//Mobile发送的总字节数
static long getMobileTxPackets()//Mobile发送的总数据包数
static long getTotalRxBytes()//获取总的接受字节数,包含Mobile和WiFi等
static long getTotalRxPackets()//总的接受数据包数,包含Mobile和WiFi等
static long getTotalTxBytes()//总的发送字节数,包含Mobile和WiFi等
static long getTotalTxPackets()//发送的总数据包数,包含Mobile和WiFi等
static long getUidRxBytes(int uid)//获取某个网络UID的接受字节数
static long getUidTxBytes(int uid) //获取某个网络UID的发送字节数
这些都是从第一次启动程序到最后一次启动的统计量。并不是这篇文章里所说的“从本次开机到本次关机的统计量”!
用法举例,注意这里得到的单位都是"KB"
Java代码
public longgetTotalRxBytes()
{
//获取总的接受字节数,包含Mobile和WiFi等
returnTrafficStats.getTotalRxBytes()==TrafficStats.UNSUPPORTED?0:(TrafficStats.getTotalRxBytes()/1024);
}
public long getTotalTxBytes()
{
//总的发送字节数,包含Mobile和WiFi等
returnTrafficStats.getTotalTxBytes()==TrafficStats.UNSUPPORTED?0:(TrafficStats.getTotalTxBytes()/1024);
}
public long getMobileRxBytes()
{
//获取通过Mobile连接收到的字节总数,不包含WiFi
return TrafficStats.getMobileRxBytes()==TrafficStats.UNSUPPORTED?0:(TrafficStats.getMobileRxBytes()/1024);
}
除了常规的这3种方法之外,还有一些流量测试的方法可以在特定场景下使用:
(1)手机设置使用pc网络,在pc端通过wireshark抓包。
(2)PC浏览器(如chrome)设置成手机的UA,通过pc浏览器自带的网络分析工具或抓包工具测试流量。此方法适用于web前端页面流量测试。
5 流量分析
测试流量大小通常只能发现问题,需要进一步定位问题则需要进行流量分析(流量分析需要方法1抓取到的pcap包)。
-
如何判断一个应用的流量消耗偏高
如果看流量的绝对值看不出高低,那就找几个同类型的产品对比一下。如果完成同样的事务,被测应用比同类产品高很多,那就是偏高了,可能有优化空间。
如下,是赶集网调用X5内核与调用系统内核打开网页的流量对比:
X5内核 |
系统内核 |
|
流量 |
656 KB |
525 KB |
可以发现,X5内核的流量更高。需要分析原因。
-
发现流量偏高如何定位问题
将网络请求资源按资源大小从大到小排列,和正常网络请求对比。发现有请求资源数量或者大小不同的地方,很可能就是问题所在。
下例中通过webperf工具,将pcap包中请求的资源分析出来。对比发现代理重复请求了2个资源:(webperf工具介绍见附录)
进一步使用wireshark查看pcap包确认图片资源有重复请求。
Follow TCP Stream查看了下这icon-status.png这个资源
发现系统内核第一次返回200,第二次返回304(因为前一次请求的时候缓存了下来),而我们代理两次返回200
http://sta.ganjistatic1.com/ng/app/client/common/image/icon-status.png
经后台开发同事定位,发现是后台图片服务器一个bug引起的。问题就此得到修复。
-
其他常见的流量问题
问题类型1:网络包数量问题
常见情况有:
(1)多余请求(本该过滤掉的广告请求,或与业务无关的请求)
(2)重复请求(同一个资源请求2次或者以上)
(3)缓存失效(本应读取缓存的资源却发起了网络请求)
(4)请求频率过高(如push心跳,如果适当提高频率可以提高业务稳定性。但过高则增加流量)
(5)可以合并的请求没有合并(通过合理合并请求可以节省流量)
(6)重传过多(终端设置的重传逻辑不合理)
(7)缺少请求(由于主资源解析出错等原因导致有些资源没有请求或请求无回应)
问题类型2:网络包大小问题
常见情况有:
(1)http包头没有压缩(有的业务为了节省流量会这样做)
(2)图片压缩不合理(后台可能根据手机型号返回不同的压缩比例的图片)
(3)其他影响网络包大小的问题(不如说网络协议、服务器逻辑出错等导致网络包大小异常)
想做更深入的流量分析。你需要掌握更多的网络知识。如:
TCP通信流程解析
http://blog.csdn.net/phunxm/article/details/5836034
6 流量测试、分析自动化
-
流量测试自动化工具
(1)Tcpdump批处理文件
将方法1的操作步骤,写一个bat去执行(tcpdump文件必须在当前目录里)。
1)开始tcpdump
adb push tcpdump/data/local/tcpdump
adb shell chmod6755 /data/local/tcpdump
adb shell rm -r/sdcard/capture.pcap
adb shell /data/local/tcpdump -i any -p -s 0 -w /sdcard/capture.pcap
pause
2)下载tcpdump文件到电脑
adb pull/sdcard/capture.pcap capture.pcap
注意:有些机器root后通过adb shell 后,默认不是root用户,需要输入 su才3)能切换到root,这样在执行批处理会有问题,解决方法如下
adb shell"su -c 'sleep 1'"
adb start-server
adb push tcpdump/data/local/tcpdump
4)因没有root权限导致的问题
adb shell su -c"/data/local/tmp/tcpdump -i any -p -s 0 -w /sdcard/netCapture.pcap"
(2)GT工具
GT的流量测试模块有2个特色功能:
1)自动生成流量趋势图:
2)在手机端操作抓取pcap包
-
流量测试自动化分析工具
(1)webperftool分析
(2)pcapperf甘特图分析
(3)chrome自带工具分析
(4)chrome trace文件分析
附录:
1、Wireshark基本用法
Wireshark基本介绍和学习TCP三次握手
http://www.cnblogs.com/tankxiao/archive/2012/10/10/2711777.html
2、过滤规则
http://blog.csdn.net/dyx1024/article/details/6649118
http://www.it165.net/safe/html/201502/1051.html
3、chrome等浏览器自带抓包工具抓包
不少pc浏览器自带抓包工具。如chrome、firefox。当我们的测试对象是一个web页面时可以使用这种方法进行流量测试。比一般抓包方法更直接而有效率。
http://blog.jaekj.com/archives/1503.html
如果你觉得抓包太麻烦,那就直接用chrome的控制台也能解决大部分问题了:
http://p2world.iteye.com/blog/1484227
http://www.cnblogs.com/qleelulu/archive/2011/08/28/2156402.html