本文由作者张雨授权网易云社区发布。
前言不知道大家在测试的过程中有没有发现关于异常测试这样一个特点:无论是分散在功能测试中的异常用例还是规模相对较大的专项异常测试中,异常测试的用例占比虽然不大但是对于挖掘问题却扮演着十分重要的角色。
随着项目组微服务化的演变进程,服务间通过 http 接口访问的场景也越来越多,本文站在测试的角度,对与 socket 的网络异常测试场景进行了一下整理和模拟方法的实践,抛砖引玉,欢迎大家提出更多更好的方法。
常见 Socket 网络异常类型异常 Exception 类型 原因 场景 connect timed out java.net.SocketTimeoutException Socket TCP 建立连接时三次握手超时,如果建立连接的时间超过了设置的 Socket 连接的超时时间触发 TimeoutException 异常 网络延迟、网络断开、网卡异常、服务端性能、客户端异常等等 Read timed out java.net.SocketTimeoutException 如果输入缓冲队列 RecvQ 中没有数据,read 操作会一直阻塞而挂起线程,直到有新的数据到来并且已经超过了设置的读超时时间时触发 客户端或者服务端进程崩溃、对方机器突然重启、网络断开等 Connection refused java.net.ConnectException 访问服务端 IP 不通或者端口服务没有启用 网络异常、服务 down 掉等 Connection reset or connection reset by peer java.net.SocketException 客户端或者服务端其中一方退出,但退出时并未关闭该连接,另一方仍然在从连接中读数据则抛出该异常(发送的第一个数据包引发该异常 Connect reset by peer 服务端并发连接数达到负载主动断开连接;客户端关闭但服务端仍读写数据网络异常场景构造实验通过上面对于异常场景原理的了解,我们通过一些 linux 网络小工具结合 tcp 的连接建立流程依次制造异常,从而更好的了解上面这些异常~
服务端:tomcat server 8080 客户端:curl 工具:iptables、tcpkill 国际惯例,tcp 三次握手非高清大图
connect timed out
客户端通过 iptables 构造异常
这里统一从出口进行流量的限制,大家也可以自己试下从入口方向做限制。
iptables -A OUTPUT -p tcp –syn –dport 8080 -j DROP 客户端访问服务端
root@asdfd-10796:~# curl http://115.238.125.169:8080 -v About to connect() to 115.238.125.169 port 8080 (#0) Trying 115.238.125.169…
Connection timed out* couldn’t connect to host
Closing connection #0
curl: (7) couldn’t connect to host 客户端查看 socket 状态:SYN_SENT
root@asdfd-10796:~# netstat -antp | grep 8080tcp 0 1 115.238.125.172:59038 115.238.125.169:8080 SYN_SENT 3692/curl
Read timed out
客户端通过 iptables 构造异常
iptables -A OUTPUT -p tcp -m state –state ESTABLISHED –dport 8080 -j DROP 客户端访问服务端
root@asdfd-10796:~# curl http://115.238.125.169:8080 -v About to connect() to 115.238.125.169 port 8080 (#0) Trying 115.238.125.169… connected Connected to 115.238.125.169 (115.238.125.169) port 8080 (#0)> GET / HTTP/1.1> User-Agent: curl/7.26.0> Host: 115.238.125.169:8080> Accept: />
additional stuff not fine transfer.c:1037: 0 0 additional stuff not fine transfer.c:1037: 0 0 additional stuff not fine transfer.c:1037: 0 0
…………………. Recv failure: Connection timed out Closing connection #0curl: (56) Recv failure: Connection timed out 客户端查看 socket 状态:ESTABLISHED
root@asdfd-10796:~# netstat -antp | grep 8080tcp 0 84 115.238.125.172:58986 115.238.125.169:8080 ESTABLISHED 3671/curl 客户端抓包情况
当 tcp 连接完成 syn-》syn ack 后进入 ESTABLISHED 状态,而由于 iptables 的配置导致服务端之后返回的 tcp 报文被 drop 掉,服务端多次重传后无 ack 返回,返回 read time out
Connection refused
客户端通过 iptables 构造异常
iptables -A OUTPUT -p tcp –dport 8080 -j REJECT 客户端访问服务端
root@asdfd-10796:~# curl http://115.238.125.169:8080 -v About to connect() to 115.238.125.169 port 8080 (#0) Trying 115.238.125.169…
Connection refused
couldn’t connect to host
Closing connection #0
curl: (7) couldn’t connect to host 客户端查看 socket 状态:FIN_WAIT1
root@asdfd-10796:~# netstat -antp | grep 8080tcp 0 85 115.238.125.172:58986 115.238.125.169:8080 FIN_WAIT1 - 服务端抓包情况
由于 iptables 的配置,客户端主动 reject 掉服务端返回的 syn ack
Connection reset by peer or connection reset
服务端通过 tcpkill 命令构造异常
tcpkill 是一个网络分析工具集 dsniff 中的一个小工具,可用来轻量级断开网络连接
tcpkill -i eth2 port 8080 客户端访问服务端
testroot@asdfd-10796:~# curl http://115.238.125.169:8080/test2 -v About to connect() to 115.238.125.169 port 8080 (#0) Trying 115.238.125.169… connected Connected to 115.238.125.169 (115.238.125.169) port 8080 (#0)> GET /test2 HTTP/1.1> User-Agent: curl/7.26.0> Host: 115.238.125.169:8080> Accept: />
additional stuff not fine transfer.c:1037: 0 0 Recv failure: Connection reset by peer Closing connection #0
curl: (56) Recv failure: Connection reset by peer 服务端查看 tcpkill 日志
root@asdfd-10649:~# tcpkill -i eth2 port 8080tcpkill: listening on eth2 [port 8080]115.238.125.172:60030 > 115.238.125.169:8080: R 3022358001:3022358001(0) win 0115.238.125.172:60030 > 115.238.125.169:8080: R 3022358230:3022358230(0) win 0115.238.125.172:60030 > 115.238.125.169:8080: R 3022358688:3022358688(0) win 0115.238.125.172:60030 > 115.238.125.169:8080: R 3022358001:3022358001(0) win 0115.238.125.172:60030 > 115.238.125.169:8080: R 3022358230:3022358230(0) win 0115.238.125.172:60030 > 115.238.125.169:8080: R 3022358688:3022358688(0) win 0115.238.125.169:8080 > 115.238.125.172:60030: R 1694916106:1694916106(0) win 0115.238.125.169:8080 > 115.238.125.172:60030: R 1694916333:1694916333(0) win 0115.238.125.169:8080 > 115.238.125.172:60030: R 1694916787:1694916787(0) win 0115.238.125.169:8080 > 115.238.125.172:60030: R 1694916106:1694916106(0) win 0115.238.125.169:8080 > 115.238.125.172:60030: R 1694916333:1694916333(0) win 0115.238.125.169:8080 > 115.238.125.172:60030: R 1694916787:1694916787(0) win 0115.238.125.172:60030 > 115.238.125.169:8080: R 3022360124:3022360124(0) win 0115.238.125.172:60030 > 115.238.125.169:8080: R 3022360386:3022360386(0) win 0115.238.125.172:60030 > 115.238.125.169:8080: R 3022360910:3022360910(0) win 0 客户端抓包情况
服务端在 tcp 连接建立后主动 down 掉连接
总结其实 socket 的异常不仅限于次如 Broken pipe、Too many open files 等,这些更多的是在压力并发测试过程中容易出现,本文介绍的这些异常更多的适用于功能性异常测试中,是发现 bug 的好帮手,大家可以在日常的测试中实验一下,会有意外收获哦
免费领取验证码、内容安全、短信发送、直播点播体验包及云服务器等套餐
更多网易技术、产品、运营经验分享请访问网易云社区。
文章来源:网易云社区