作者:xiaobiao
在日常业务中QC经常遇到一些难以模拟的使用场景,如PM有一个需求是在网络不友好(俗称弱网)环境下用户也能否正常使用或者是否会自动切入预定备用线路,但往往手里没有线上场景可以实际测试,QC也很难通过在测试环境下模拟线上用户进行操作使用。
所以基于以上情况,为解决无法弱网评估的痛点,实现研发团队对业务的弱网兼容测试,故设计了此套系统,此系统设计可能并不是特别完善,仅作抛砖引玉之用。
整套系统角色主要分成三个:
netem是Linux 2.6及以上内核版本提供的一个网络模拟功能模块。该功能模块可以用来在性能良好的局域网中,模拟出复杂的互联网传输性能,诸如低带宽、传输延迟、丢包等等情况。使用 Linux 2.6(或以上)版本内核的很多发行版Linux都开启了该内核功能,比如Fedora、Ubuntu、Redhat、OpenSuse、CentOS、Debian等等。
tc是Linux系统中的一个工具,全名为traffic control(流量控制),默认在原装的Linux系统就自带有这个命令。tc可以用来控制netem的工作模式,也就是说如果想使用netem,需要至少两个条件:一个是内核中的netem功能被包含,另一个是要有tc。tc可以用来模拟网络丢包和延迟,在开发后台server时,如果我们想要知道这个server在特定的网络丢包情况下,是否能表现良好,就可以用tc来模拟丢包率。基本原理:
接收包从输入接口进来后,经过流量限制丢弃不符合规定的数据包,由输入多路分配器进行判断选择。如果接收包的目的地是本主机,那么将该包送给上层处理,否则需要进行转发,将接收包交到转发块处理。转发块同时也接收本主机上层(TCP、UDP等)产生的包。转发块通过查看路由表,决定所处理包的下一跳。然后,对包进行排列以便将它们传送到输出接口。
需要注意的是:此处说的流控只能控制发包动作,不能控制收包动作,同时,它直接对物理接口生效,如果控制了物理的eth0,那么逻辑网卡(比如eth0:1)也会受到影响,反之,如果您在逻辑网卡上做控制,该控制可能是无效的。(注:虚拟机中的多个网卡可以在虚拟机中视为多个物理网卡)
其他注意事项:
流量的处理有三种对象控制:
其中 qdisc 和 filter 比较常用,class 一般用于流量控制等高级应用,三种对象命令格式如下:
tc qdisc [add | change | replace | link] dev DEV [parent qdisc-id | root] [handle qdisc-id] qdis c [qdisc specific parameters] tc class [add | change | replace] dev DEV parent qdisc-id [classid class-id] qdisc [qdisc specifi c parameters] tc filter [add | change | replace] dev DEV [parent qdisc-id | root] protocol protocol prio priorit y filtertype [filtertype specific parameters] flowid flow-id
当然,tc 全部使用方式展开来可以写一本书,本文仅展示大致的说明和其弱网控制的应用。
百闻不如一见,百见不如一干,我们简单来用下这个 tc 弱网工具;假设有 AB 两台机器,A 机器设置弱网参数,B 机器一直 pingA 机器查看延迟。
在测试前,可以明显看到 B->A 延迟都是在 1ms 内,然后在 A 机 eth0 网卡加上 233ms 延 迟策略
tc qdisc add dev eth0 root netem delay 233ms
可以看到延迟立马上升到233ms延迟,然后清理弱网策略
tc qdisc del dev eth0 root
可以看到网络延迟在清理策略后立马就恢复了,同样使用丢包命令也是一样,如
tc qdisc add dev eth0 root netem loss 40%
设置40%的丢包率,ping100个包,结果如下图,丢包率一般都会徘徊在40%左右。
弱网策略机接受到的指令无非新增、更新、删除、重置策略这四大操作,机器根据中控机的总指令判断该请求属于哪一类型,然后执行相应的操作。
本次演示机器假设网卡为eth0、vpn默认端口5555,Hub名称为VPN作为例子进行命令操作,提供相关关键语句进行说明。
删除规则其实就是把以前原机器的规则全部删掉,命令也就一句:
tc qdisc del dev eth0 root
初始化包括两大步,一是初始化文件夹,创建等会最后切割日志文件夹和清空相关日志,二是将原先机器中VPN的对应账户进行删除,同时不管有无会话都需要关闭一次,杜绝其他影响。
#找出申请账号是否存在,存在需要先删除 vpncmd localhost:5555 /SERVER /Hub:VPN /CMD:UserGet 用户名 #如果找出就删除 vpncmd localhost:5555 /SERVER /Hub:VPN /CMD:UserDelete 用户名 #找出所有会话 vpncmd localhost:5555 /SERVER /Hub:VPN /CMD:SessionList #如果找出后进行删除会话 vpncmd localhost:5555 /SERVER /Hub:VPN /CMD:SessionDisconnect 具体会话名称
创建用户分为创建、设置密码、设置账号有效期三步,对应命令如下:
#创建用户(如无特殊情况组、名称、备注等信息可不填) vpncmd localhost:5555 /SERVER /Hub:VPN /CMD:UserCreate 用户名 /GROUP:none /REALNAME:none /NOTE:none #修改密码 vpncmd localhost:5555 /SERVER /Hub:VPN /CMD:UserPasswordSet 用户名 /PASSWORD:用户密码 #设置账号有效期 vpncmd localhost:5555 /SERVER /Hub:VPN /CMD:UserExpiresSet 用户名 /EXPIRES:"账户有效期时间(格式:2020-08-08 08:08:08)"
更新弱网规则为最重要部分,常用的弱网规则无非是丢包和延迟,再高级一点的如指定端口或者IP,再上级一点可以限速等,这次示例篇幅有限仅演示到指定端口或者IP,根据常规组合可以组合如下选择:
常规全局需要注意由于弱网策略作用在VPN机器网卡出口处,如果直接设置弱网规则会变成双向计费,所以需要提前打个折,如需要加上延迟100ms,在策略机上加上的策略就是50ms,一来回就变成了100ms。
当然,对于丢包不是简单打5折,如需要设计丢包率为40%,那么设置在机器丢包率为x,满足,最后得到,最后得到x约为22.55%,由于Linux的Shell不支持根号计算,此处可以用python简单根号计算然后返回再计算。
#coding:utf-8设置字符编码 import math c = {需要计算的数字} print(math.sqrt(c))
最后执行弱网策略
#设置总规则 tc qdisc add dev eth0 root handle 1: prio #设置白名单延迟规则,策略为1ms tc qdisc add dev eth0 parent 1:3 handle 30: netem delay 1ms #加上弱网参数 tc qdisc add dev eth0 parent 1:3 handle 30: netem 弱网参数 #给主控机加上白名单,防止因为弱网策略导致发送命令失败,使用策略1:3 tc filter add dev eth0 protocol ip parent 1:0 u32 match ip dst 主控机IP/32 flowid 1:3 #可以再给公司出口加上白名单,这样若主控机异常无法操作还能手动操作 tc filter add dev eth0 protocol ip parent 1:0 u32 match ip dst 出口IP/32 flowid 1:3
PS:弱网参数中delay延迟和loss丢包可以组合在一起也可以分开,如【delay 100ms loss 40】或【delay 200ms】,根据用户需求发送指令即可。
指定参数弱网相对比较简单,由于是指定端口/IP,那么弱网策略只是针对这个指定端口/IP,不需要提前打折。不过不同的指定组合不能像刚才那样随意组合需要注意顺序,而且默认需要加上弱网参数(不然指定了也没意义)。
同时指定IP和端口:
#设置总规则 tc qdisc add dev eth0 root handle 1: prio #设置当前的弱网参数 tc qdisc add dev eth0 parent 1:3 handle 30: netem 弱网参数 #加入指定参数 tc filter add dev eth0 parent 1:0 protocol ip prio 1 u32 match ip dport 指定端口 0xffff match ip dst 指定IP flowid 1:3
指定端口:
tc qdisc add dev eth0 root handle 1: prio tc qdisc add dev eth0 parent 1:3 handle 30: netem 弱网参数 tc filter add dev eth0 parent 1:0 protocol ip prio 1 u32 match ip dport 指定端口 0xffff flowid 1:3
指定IP:
tc qdisc add dev eth0 root handle 1: prio tc qdisc add dev eth0 parent 1:3 handle 30: netem 弱网参数 tc filter add dev eth0 protocol ip parent 1:0 u32 match ip dst 指定IP flowid 1:3
删除用户时需要注意先删除用户会话再删除账号,因为设置账号有效期一般是代表过了有效期后用户不能登陆,但是如果用户此时一直在线是没有限制,需要从会话列表找到对话并主动掐断,再继续删除账号,操作命令基本和初始化机器一致。
切割vpn日志一般看业务方需求,毕竟vpn属于公共服务,不能用于违法事宜,日志也一般用作后期审计使用,在主控机发送指令时可以同时产生一个独一无二的code(如时间戳等)用于标记当前任务,后续如果有问题再溯源就有依据可行。
cp 旧日志 新日志位置
tc是一个非常强大的工具,在掌握tc的基本使用方法后也可以根据实际的业务需求进行调整,如模拟随机弱网,简单写个脚本进行loop:先tc命令设置好延时–>隔随机时间后–>将tc规则删除–>再隔随机时间后–>tc命令加入延时,如此往复即可实现。
弱网测试目前也是属于小众但也比较难以模仿的测试项目,这就是本套系统存在的意义,各位根据语句可以自行修改,Enjoy yourself~