网络延迟与带宽性能专项测试

陈帅 2017-10-11 390 标签: 性能测试测试网络

概述

代理、VPN作为两种古老的数通网络安全解决方案,在当今移动互联网时代,伴随着游戏网络加速、WiFi安全性等用户硬性需求,再次焕发青春。

在数通网络中,VPN一般拓扑如下图一。需要测试VPN系统的网络性能,只需要使用背靠背网络(如图二),测试仪器从Client端发包,Server端收包,就可以轻松测算到系统带来的延时、丢包、网络的吞吐性能以及TCP新建、并发等性能指标。IETF组织的RFC2544和RFC3511也详尽的阐述了如何测算这些指标。而这些指标,也会成为设备供应商参与竞标必备的技术指标,采购方也会详细对比各厂商的设备性能,再决定采购谁的设备。

图一 数通网络VPN一般拓扑

图二 背靠背测试网络

同理,在移动APP测试范畴内,我们也需要进行可靠的竞品测试,验证自己产品提供的VPN、proxy服务,性能是否优于竞品。顺理成章,笔者首先想到的是,能否搭建一套类似于图二的背靠背网络来测试其网络性能?马上会出现两个问题:

  1. 笔者无法搭建测试环境的竞品Vpn Server Gate所知;竞品的实现方案也不为笔者所知;

  2. 在快节奏的互联网产品迭代中,也不允许如此复杂的测试环境搭建。

不管怎样,借鉴其思路,我们还是能够找到一个可行的的方案来获取可靠的竞品对比数据。

测试方法篇

延迟、带宽这类指标,都需要在大量样本上运用统计学进行分析才是有意义的。所以收集数据,是专项性能测试的第一步。

在简单的网络测试中,我们一般采用ICMP来进行网络延迟检测。笔者选用的方案并不是简单的ICMP,而是HTTP GET一个单数据包能够容纳的页面。而带宽测试,则是通过HTTP下载一个500M左右的文件,并记录每一秒收发数据量来获得带宽数据。

这样选择,主要有两方面原因。

一、从业务上说,Android的VpnService按应用导入流量,ping程序的ICMP包不会进VPN,导致测试数据错误;同时,TCP和UDP的流量更贴近用户场景的真实流量。

二、从测试方案上说,使用HTTP的接入成本更低。这样延迟、带宽等各种参数均可以使用同一个数据接口来实现。

延迟测试原理

相比于使用背靠背网络,可以测得数据单向传输所需的时延。在笔者的方案中,单位数据样本是计算测试APP发出HTTP GET请求,到收到 200 OK的响应所耗时长。如下图,这次延迟的数据,计算的是发出52号包,到收到59号包所耗用的时长222ms。

延迟测试HTTP GET数据的选择,笔者是选用的是http://httpbin.org/ip 。原则是尽量选择GET内容能够单个IP数据包能够返回的页面。

图三 延迟测试抓包

如果没有现成的好用的target,笔者推荐httpbin。它有点像一个蜜罐,时刻等待着你的光临,然后根据你的请求,给你返回你想要的东西。我们可以放心大胆的黑他,而不用担心他报复你。(官网| github)唯一的缺点是,这东西在美国,未加VPN之前的访问延迟和抖动就比较大。(要吐槽下,为什么免费的,好用的,技术性的东西,都在美国?)。图三的截图,就是get httpbin.org/ip 的结果。

延迟测试逻辑

在coding阶段,为了更低的代码成本。笔者选用了Retrofit,而不是自己去实现一大堆网络通信的东西。当然,作为一个深爱技术的测试,深入去理解下原理还是非常有必要的(Retrofit官网)。具体的Retrofit使用方法不详细介绍,有兴趣的同学可以详细了解官网或CSDN的例子。

如下代码中,需要注意下call.execute()的第一次执行,start的时间点是在TCP三次握手首包SYN之前,end是在收到HTTP 200 OK回应之后,所以首包的时延会比较长。尤其是在测试代理场景时,因为proxy先跟client建立tcp连接,再去跟server三次握手,然后才是数据转发。在选择样本时,可以选择过滤掉首次数据。但是,别忘了,首包时延值,其实也可以成为你衡量一个VPN系统或Proxy系统性能的关键指标。


Call<ResponseBody> call = repo.getMmgr();
start = System.currentTimeMillis();
Response response = call.execute();
if (response.code() == 200) {
    end = System.currentTimeMillis();
    long delay = end - start;
    DataSaveHandler.openFileWriter(dataSavePath);
    DataSaveHandler.writeNewLine(mLogSdf.format(start) + "," + delay);
    DataSaveHandler.saveAndCloseFile();
    Thread.sleep(interval);
}

带宽测试原理

带宽测试分两步,先拉起一个线程使用Retrofit接口去下载一个大文件。然后拉起另一个每隔两秒去收集一下WiFi wlan0接口的发包数据和收包数据量。

其实在Android的流量类android.net.TrafficStats中,getRxBytes和getTxBytes是隐藏方法,而getTotalRxBytes()和getTotalTxBytes()是可以直接调用的方法。为什么要选用隐藏的而不是后者呢?

因为,笔者测试的测试目标是VPN性能,在VPN中,测试对象会拉起一个tun0的接口。如果使用getTotalRxBytes这两个方法,它们统计的流量就将tunnel口的收发数据也统计进来了。这样会导致数据整体不准确。

以下,是调用到TrafficStats.getRxBytes的关键代码。全量代码依然可以在上面提及的KM文中找到。

Class<?>claxx = Class.forName("android.net.TrafficStats");
mgetRxBytesMethod= claxx.getDeclaredMethod("getRxBytes", String.class);
mgetTxBytesMethod= claxx.getDeclaredMethod("getTxBytes", String.class);
mgetRxBytesMethod.setAccessible(true);
mgetTxBytesMethod.setAccessible(true);

综上所述,笔者实现了一个小的APP,给它命名为悟空。MainActivity负责提供一些按钮触发测试;各个测试线程用来跑逻辑测试逻辑;DataSavaHandler负责将数据写入sdcard存成csv文件。

图四 悟空的结构

数据分析篇

对于延迟数据,建议使用中位数方差来衡量衡量总体延迟和抖动。原因如下,如果执行100次之后,数据可能是如下图的。大部分数据都在1s以内,有少量几个数据是在1s以上。但由于这几个异常值过大,几乎是一般延迟的20倍左右,如果使用均值来计算的话,会导致偏差过大。

图五 延迟数据

数据示意如下,Excel计算公式参考:

均值=AVERAGE(NoVPN_1!B2:B101)

方差=STDEV.P(NoVPN_1!B2:B101)

中位数=MEDIAN(NoVPN_1!B2:B101)

当然,上表的数据,其实还是不太直观的。笔者从自己的测试数据中抽取了以下两组数据来观察。如果从均值来看,两者似乎很接近。但中位数却表明样本B的延迟要远小于样本A。从方差分析,样本B中肯定是存在某些波动很大的数据导致均值偏大。

时延ms 样本A 样本B
均值 93.72 90.98
方差 42.42 78.02
中位数 86.50 68.00

这里反应的背景是,我们的测试并不像数通网络测试一样,将测试链路与真实通信链路隔开。延迟数据中,带入延迟的,可能是我们的VPN系统,也可能是网络中某个节点的突然波动。所以补充下面的数据分析是非常必要的。

Excel公式:

 =COUNTIF(Qiandun_1!D2:D101,">150")/COUNT(Qiandun_1!D2:D101)
时延 样本A 样本B
大于80ms 16.00% 72.00%
大于100ms 14.00% 23.00%
大于150ms 11.00% 0.00%

这样,从延迟上看,样本B确实远逊于样本A,72%的延迟数据都在80ms以上。而样本A中只有16%的数据在80ms以上。得出这样的结论,是因为延迟数据的波动是一个单向波动的数据:在一定的基础延迟下,延迟数据只可能正向抖动,物理规则决定不会抖动出一个非常小的数据。如网络原有的延迟50ms,新加入节点带来的抖动,只可能使得总体延迟大于50ms。

结语

移动互联网的性能测试,很多时候需要我们快速输出报告,还要求数据可靠性高。这样,就要求测试人员在很好的理解需求之下,在需求提测前将一些数据收集的行为自动化成工具。同时,要有良好的数据分析能力,能够让自己的测试结论更具说服力。

文章来源于:腾讯移动品质中心 TMQ