标签:
在解决日常的支持需求中,经常会遇到一些用户反馈一些无法简单复现的bug,有很大一部分的bug是由于用户自身的网络环境波动,或者是本身网络环境就较为恶劣,而服务在面对这种恶劣的网络环境的健壮性不够,导致会出现一些意想不到的bug。而在正常的开发自测过程中很难去营造出这种恶劣的网络环境,使得这些bug较难被提前发现和修复。另外一些服务在恶劣网络环境下虽然不会出现不可用的情况,但是用户体检很差,为了优化这个情况下的用户体验,也需要去在本地模拟这种环境来进行调优。
所以要去复现这些bug,甚至是去提前发现这些bug,就需要能够在开发环境中模拟出恶劣的网络环境,从而看到在这种恶劣的网络环境下的服务的表现等。当前模拟恶劣网络环境主要可以通过以下这些手段实现:
这里主要先讲的是第一种手段,即利用Fiddler来模拟恶劣的网络环境,对服务进行测试,这个手段实现简单,较为直观,但是缺点是只能支持那些利用HTTP进行通信和交互的服务。在之后的文章中也会进一步说一下后两种手段。
Fiddler的官网上是这样描述它自己的:The free web debugging proxy for any browser, system or platform,即跨浏览器、跨系统、跨平台的免费Web Debug代理服务器。当你的HTTP浏览经过Fiddler时,Fiddler可以监视流量,查看HTTP通讯的各种信息,设置断点查看和修改HTTP数据,甚至可以构造各种测试用的HTTP包以及重放已记录的包等。其官网是http://www.fiddler2.com/fiddler2/,上面详细地介绍了Fiddler到底是什么。
Fiddler本身已经预置提供了模拟Modem速度的选项,其位置位于:
Rules – Performances – Simulate Modem Speeds
勾选该选项后,所有通过Fiddler代理的流量都会变得和多年前的56k小猫时上网一般的慢。
由于Fiddler只是一个HTTP代理,要直观地看出限速效果,最好是运行在浏览器中的测速工具,这里选用speedtest.net提供的测速工具进行测试。
首先是开启该选项之前的速度:
打开了Simulate Modem Speeds后:
速度已经回到了当年那种无法忍受的低速了,注意到这里PING值也有了显著的提高,而事实上ping值是ICMP层的控制报文,并不会被Fiddler影响,理论上ping值并不会出现提高的情况,进一步分析Fiddler中的报文则可以看出端倪:
事实上网页插件并不能实现发送ICMP包并得到ping值的功能,而是用多次较小的HTTP GET请求的响应时间来计算PING值,这里实际算出来的是一个平均的HTTP的RTT值,所以受到Fiddler模拟恶劣环境的影响就是正常的了。
直接模拟Modem速度实在是慢爆了,事实上就算是在很差信号的情况下,手机移动网络的速度都已经超过了当年的56k Modem速度了,所以采用默认的配置模拟出来的环境过于恶劣,并不一定符合需求,此时就需要对限速的参数进行调整。
Fiddler本身就提供了一个配置文件供调整这些参数,点击:
Rules – Customize Rules…
就会用文本编辑器打开CustomRules.js文件,其默认位于用户目录的文档目录下的\Fiddler2\Scripts 位置,后缀名是js,其内容实质是JScript.NET——微软对ECMAScript规范的实现,与日常使用的javascript是属于同一个规范下的,但是在扩展的细节实现存在一定的不同。
打开该文件后,可以找到一个m_SimulateModem标志位:
if (m_SimulateModem) {
// Delay sends by 300ms per KB uploaded.
oSession["request-trickle-delay"] = "300";
// Delay receives by 150ms per KB downloaded.
oSession["response-trickle-delay"] = "150"
}
上传带宽=(1*8/1000)/0.300≈0.053Mbps
下载带宽=(1*8/1000)/0.150≈0.027Mbps
然而实际情况下却得到了两倍于这个值的带宽,推测可能是Fiddler的内部实现上有一些和描述上的不同,为何为造成这个现象现在还不是很清楚,所以上述公式最后还需要修正一个2.0的系数,即:
上传带宽=((1*8/1000)/0.300)*2.0≈0.106Mbps
下载带宽=((1*8/1000)/0.150)*2.0≈0.053Mbps
假设我们将两个参数都设置为50,则会得到上下载带宽均为0.32Mbps,测速结果如下所示:
进一步地,我们可以扩展CustomRules.js里的逻辑,参照Jscript的文档可以在模拟恶劣环境中加入更多自定义的逻辑,这里实现了一个随机延时量设置,使得网络带宽不是恒定为一个低速的值,而是会在一定范围内随机抖动:
static function randInt(min, max) {
return Math.round(Math.random()*(max-min)+min);
}
if (m_SimulateModem) {
// Delay sends by 300ms per KB uploaded.
oSession["request-trickle-delay"] = ""+randInt(1,50);
// Delay receives by 150ms per KB downloaded.
oSession["response-trickle-delay"] = ""+randInt(1,50);
}
得到的测试结果如下:
在测速过程中的瞬时速度的趋势图如下:
可以看到整体的网络限速存在了一定程度的抖动。
通过进一步扩展CustionRules.js可以实现很多需要的恶劣环境模拟场景,如果场景较为复杂的话,也可以通过编写Fiddler的插件的方式,编写C#插件代码来进一步控制Fiddler的行为,在这里就不多做赘述了。详细可以参照:http://docs.telerik.com/fiddler/extend-fiddler/extendwithdotnet
Fiddler进行限速较为简单和灵活,配置也较为方便,但是由于它是一个应用层的HTTP的代理,只能模拟该层上的行为,对于一些复杂的网络层的丢包、重传等恶劣情况就不能很好的模拟出来,而且对于其他协议的应用也不支持,后续会介绍一些其他的模拟恶劣环境的方法和软件来弥补这些缺失。
在之前的文章中提到了三种模拟恶劣网络环境调试代码的手段:
同时在之前的文章中介绍了第一种手段,即利用应用层的HTTP代理Fiddler来模拟恶劣网络环境,这种方式简单且灵活,但是其处于应用层,限制较大,同时也没有办法从带宽和延时两个方面分别去精细化地对恶劣网络环境进行模拟,这里介绍第二种手段——Dummynet。
Dummynet的官网地址是:http://info.iet.unipi.it/~luigi/dummynet/,官网上对于dummynet的描述是这样的:dummynet is a live network emulation tool, originally designed for testing networking protocols, and since then used for a variety of applications including bandwidth management. 即Dummynet是一个实时的网络模拟工具,事实上dummynet是ipfw防火墙的一部分,ipfw是一个网络层的防火墙,并内建于FreeBSD之中。
利用ipfw的options DUMMYNET选项,可以设置一系列的pipes,从而做到对网络流量进行控制的目的。
如官网上提供的这张图所示,dummynet通过在两个网络层中(一般是在传输层和应用层之间或者网络层与传输层之间)建立一条条pipe的方式来控制网络流量,符合设定的规则中的网络流量会被引入这些管道中去,从而使得dummynet可以介入这些流量之中,控制带宽、延迟,甚至进一步控制丢包率等众多参数。
Dummynet本身作为ipfw防火墙的一部分,其内建于FreeBSD,其本身支持FreeBSD,OSX,Linux,Windows多种操作系统下的安装和使用,在OSX和Linux下下载源码编译安装一般即可使用,这里主要介绍一下Windows下的Dummynet安装。
Dummynet在Windows下是作为一个网卡上的服务驱动存在的,在官方给出的二进制文件包中已经包含了该驱动的sys与inf文件,但是该驱动是没有包含数字签名的,在并没有引入驱动强制签名机制的Windows操作系统(如Windows XP)上时,直接到官网下载到最新的二进制包,然后依照之后的操作步骤进行安装即可以完成ipfw+dummynet服务驱动的安装,但是在引入了驱动强制签名机制(一般是Windows 7以后的Windows版本,或者设置了比较严格的组策略)的操作系统上,是无法安装ipfw+dummynet服务驱动的,要解决这个问题可以使用两种方案:
安装的方式如下:
利用dummynet的pipe,可以设置一些特定的规则,就可以达到模拟恶劣网络环境的目的,且这些设置对于在操作系统中运行的应用程序来说是透明的、自动生效的,不需要像在使用Fiddler来进行模拟时还需要设置http代理。
ipfw add pipe 2 in proto tcp
ipfw pipe 2 config bw 2Mbit/s
ipfw add pipe 10 ip from any to any
ipfw pipe 10 config delay 200
ipfw add pipe 10 ip from any to any
ipfw pipe 10 config plr 0.1
ipfw add pipe 4 src-ip 10.1.2.0/24 in
ipfw pipe 4 config bw 1Mbit/s delay 123 plr 0.1
在最后,当完成模拟恶劣网络环境后,执行以下命令: ipfw -q flush
ipfw -q pipe flush
来清除所有设定的pipe和规则,进一步如果需要还原原来的环境的话可以将驱动删除,并重启计算机即可。
clumsy 能在 Windows 平台下人工造成不稳定的网络状况,方便你调试应用程序在极端网络状况下的表现。
利用封装 Winodws Filtering Platform 的WinDivert 库, clumsy 能实时的将系统接收和发出的网络数据包拦截下来,人工的造成延迟,掉包和篡改操作后再进行发送。无论你是要重现网络异常造成的程序错误,还是评估你的应用程序在不良网络状况下的表现,clumsy 都能让你在不需要额外添加代码的情况下,在系统层次帮你达到想要的效果:
特色:
下面的动画展示了 clumsy 作用于一个本地的基于 netcat 的 UDP 服务器/客户端的情况。仔细观察你可以看到数据根据在 clumsy 的影响下产生了相应的变化。 如果你基本知道了 clumsy 是干什么用的,不妨到下载页面选择适用于你系统的版本进行下载。
clumsy 首先根据用户选择的 filter 来拦截指定的网络数据。在 filter 中可以设定你感兴趣的协议(tcp/udp),端口号,是接收还是发出的端口。你也可以通过简单的逻辑语句来进一步缩小范围。当 clumsy 被激活时,只有符合这些标准的网络数据会被进行处理,而你不感兴趣的数据仍然会由系统正常传输。
当被 filter 的网络数据包被拦截后,你可以选择 clumsy 提供的功能来有目的性的调整网络情况:
尽管当前宽带网络连接十分普及,但网络传输其本身在本质上总不是稳定的。如果你的应用程序中没有应对各种情况的处理,那么有可能一个丢失的 UDP 包裹都会让你的程序崩溃。正确的调试这类行为 显然需要再代码结构上进行仔细的设计和处理,还会很花功夫。而且在某些封装紧密的开发环境(Unity3D 自带的网络库可能是一个例子)下会更麻烦。clumsy 以尽可能减轻程序员负担为目标, 希望提供一个简单方便(但并不完美)的解决方案。
项目的代码可以在github上获取。在下载页面有编译好的版本。强烈建议在使用前花点时间阅读一下文档,来 了解 clumsy 的功能和限制。
标签:
原文地址:http://www.cnblogs.com/jinjiangongzuoshi/p/5272787.html