使用RCT实现Linux服务器的网络控制

前言

在某一个月黑风高的晚上,小A要进行异常场景测试。但是很长时间以来异常场景的模拟都是小A觉得很麻烦的地方。小A的异常模拟主要分为两个部分:

  • 模拟网络中断
  • 模拟网络延迟和丢包

这些场景的模拟有以下两个棘手的地方:

  • 模拟异常的方法
  • 异常时间的控制

小A掐指一算,想要模拟网络中断,有以下几个方法:

  • 拔掉网线
  • 禁用网卡
  • 重启机器
  • 使用防火墙策略

前三个方法费事费力,时间上不好控制,而且物理机房更是无法触碰的禁区。小A决定使用第4个方法,在Linux系统中配置防火墙策略需要使用iptable命令。但是这个命令配置参数众多,不好上手,而且还需要时间来调试。怎样控制中断的时间?如何保证在测试程序异常退出后网络中断可以自动恢复,不会影响到下一次测试?就算这个可以搞定,延迟和丢包如何模拟?
望着窗外冰冷如刀的月光,小A已经不愿多想......

为了模拟以上网络异常,RCT提供了一系列的方法,只需要简单调用,就可以轻松模拟。

网络控制功能

流控功能——设定网络延时

设置和清除网络延时,范围为(0, 1000],单位:毫秒
设置方法:

//设置网络延迟milliseconds毫秒,持续delayMinute分钟 boolean setNetworkDelay(int milliseconds, int delayMinute)//设置网络延迟milliseconds毫秒,持续delayMinute分钟,triggerMinute分钟后生效 boolean setNetworkDelay(int milliseconds, int delayMinute, int triggerMinute)

清除方法:

//清除网络延迟 void clearNetworkDelay()

流控功能——设置和清除网卡丢包

设置和清除网卡丢包,范围为(0%, 50%],单位:百分比
设置方法:

//设置网络丢包percent%,持续delayMinute分钟 boolean setPackageLoss(int percent, int delayMinute)//设置网络丢包percent%,持续delayMinute分钟,triggerMinute分钟后生效 boolean setPackageLoss(int percent, int delayMinute, int triggerMinute) 

清除方法:

//清除网络丢包 void clearPackageLoss()

注意:目前不能够同时设置延时和丢包,后一个设置的项目会覆盖前一个。

例子:

SSHUnit sshUnit = new SSHUnit();
sshUnit.setIp("192.168.0.1");
sshUnit.setUserName("username");
sshUnit.setPassword("password");SSHClient sshClient = new SSHClient(sshUnit);//使用建立好的SSH客户端初始化一个流量控制器 TrafficController tc = new TrafficController(sshClient);//设置网络延迟100ms,持续3分钟 tc.setNetworkDelay(100, 3);//可以再解除时间没有到的时候手动解除,但是由于网络延迟或丢包,有可能不生效 tc.clearNetworkDelay();//设置网络丢包2%,持续1分钟,1分钟后生效 tc.setPackageLoss(2, 1, 1);//可以再解除时间没有到的时候手动解除,但是由于网络延迟或丢包,有可能不生效 tc.clearPackageLoss();

接入控制——阻止本机到其他机器的通信

//阻止本机到某个IP的全部通信,持续delayMinute分钟 boolean blockIP(String ip, int delayMinute)//使本机丢弃掉所有来自于某个IP的消息,持续delayMinute分钟 boolean blockIPInput(String ip, int delayMinute)//使本机丢弃掉所有去往某个IP的消息,持续delayMinute分钟 boolean blockIPOutput(String ip, int delayMinute)//阻止本机到某个IP的全部通信,持续delayMinute分钟,triggerMinute分钟后生效 boolean blockIP(String ip, int delayMinute, int triggerMinute)//使本机丢弃掉所有来自于某个IP的消息,持续delayMinute分钟,triggerMinute分钟后生效 boolean blockIPInput(String ip, int delayMinute, int triggerMinute)//使本机丢弃掉所有去往某个IP的消息,持续delayMinute分钟,triggerMinute分钟后生效 boolean blockIPOutput(String ip, int delayMinute, int triggerMinute)

接入控制——解除本机到其他机器的通信

//解除本机对某个IP的通信禁止 boolean unblockIP(String ip)//使本机重新接受所有来自于某个IP的消息 boolean unblockIPInput(String ip)//使本机重新接收所有去往某个IP的消息 boolean unblockIPOutput(String ip)//清除所有设置 void clearAll()

注意:由于iptables防火墙不会自动过滤重复的配置,故对于同一个IP或端口的禁止设置务必只执行一次,如果多次执行,则在解除禁止的时候也需要相同次数的解除,才能生效。

例子:

SSHUnit sshUnit = new SSHUnit();
sshUnit.setIp("192.168.0.1");
sshUnit.setUserName("username");
sshUnit.setPassword("password");SSHClient sshClient = new SSHClient(sshUnit);//使用建立好的SSH客户端初始化一个接入控制器 AccessController ac = new AccessController(sshClient);//阻止192.168.0.1这台机器发送到xx.xx.xx.xx的一切通信,1分钟后自动解除 ac.blockIP("xx.xx.xx.xx", 1);//可以在时间未到之前手动解除 ac.unblockIP("xx.xx.xx.xx ");//阻止192.168.0.1这台机器发送到xx.xx.xx.xx的一切通信(并不阻止接受),1分钟后自动解除,1分钟后生效 ac.blockIPInput ("xx.xx.xx.xx", 1, 1);
ac.unblockIPInput("xx.xx.xx.xx ");

原理

模拟网络异常的原理很简单,Linux已经提供好了相应的命令:

通过使用RCT提供的异常模拟方法,大大减少了重复代码的编写和调试。让测试人员能够将精力更多的放在具体的测试场景上。

如果有更好的意见或者建议,或者有使用中不爽的地方,或者是找到了bug,欢迎随时联系和骚扰。

在下一集里,小A又将经受怎样的磨难,他又将如何化解呢?
欢迎关注Java与Linux交互的利器——RCT系列文章(三)