4、TCPCopy核心技术
TCPCopy核心技术有TCP领域知识、服务器领域知识、伪造技术和模拟上层交互行为的技术。
4.1 TCP领域知识
1. 流量控制
2. 重传
3. 定时器
4. 序列号计算
5. 状态控制
6. 网络延迟控制
4.1.1 流量控制
流量控制常应用在如下场景中:
流量控制的目的是控制数据发送速度以匹配测试环境的处理速度。盲目发送大量数据给测试服务器,只会导致测试服务器TCP接收缓冲区满,测试变得不真实或者无法进行下去。
4.1.2 重传
TCPCopy重传数据包的目的是保证高并发情况下的数据传输,减少丢包对后续请求传递的影响。
TCPCopy机器到测试服务器往往是在同一个网段,网络拥塞的可能性不大,因此丢包一般发生在测试服务器端,丢包的主要原因是流量控制不当。
4.1.3 定时器
TCPCopy的定时器控制着超时重传,延迟发送ack确认,延迟发送请求数据包,重构连接等过程。
由于Linux定时器的精度是有限的,我们以1ms作为最小时间单位。
4.1.4 序列号计算
序列号计算是请求复制成功的关键。
序列号计算常用在如下情况:
1. 对测试服务器payload响应的ack确认
2. 对测试服务器第二次握手数据包的确认
3. 对测试服务器FIN数据包的ack确认
4. 根据客户端数据包的ack sequence,判断出请求的边界。
4.1.5 状态控制
TCP需要状态控制,TCPCopy也同样需要。
TCPCopy涉及到的状态如下:
TCPCopy中的TCP状态跟内核TCP状态不一样,原因如下:
4.1.6 网络延迟控制
网络延迟控制是为了模拟在线的网络延迟,使得测试更加逼真。
在以下场景中需要考虑延迟控制:
4.2 服务器领域知识
我们从下面方面讲述TCPCopy涉及到的服务器知识。
1. cache友好性
2. 内存控制
3. 数据结构和算法
4. 资源清理
5. 鲁棒性
6. 底层高效处理
7. 合并TCP/IP header
8. 内网和外网特征
4.2.1 cache友好性
开发服务器程序,需考虑程序的性能,TCPCopy也不例外。
在以下处理方面,TCPCopy充分考虑了cache友好性:
1. 同一个session处理所消耗的内存尽量放到一起,防止cache miss
2. intercept集中存放路由信息,这个优化使intercept的整体性能提升了30%
4.2.2 内存控制
由于涉及到大量数据包处理,需控制内存消耗量。
内存控制的好处有如下方面:
1. 减少程序对内存的需求,从而提升程序的性能
2. 防止内存泄漏
3. 防止挤占在线宝贵的内存资源
4.2.3 数据结构和算法
TCPCopy所采用数据结构和算法需考虑以下细节:
4.2.4 资源清理
为了方便用户测试,TCPCopy采用reset数据包来清理服务器资源。
有些TCP状态,需要等几分钟才能消失,例如TIME_WAIT状态、FIN_WAIT1和FIN_WAIT2状态。通过reset数据包可以快速消除测试服务器的TCP状态,从而规避了重启TCPCopy所面临的麻烦。
4.2.5 鲁棒性
通过如下措施来提升TCPCopy的鲁棒性:
4.2.6 底层高效处理
在数据包处理方面,越靠近网卡,处理效率越高。
在数据链路层发包,和IP发包(TCPCopy默认)相比,吞吐量可以提升30%。
TCPCopy支持在数据链路层发包,具体可以参考"" 。
4.2.7 合并TCP/IP header
intercept捕获到响应数据包后,不会立即发送响应包的TCP/IP header给tcpcopy,而是先把数据包的TCP/IP header放到发送buffer队列中去。
只有满足如下条件之一才能发送给tcpcopy:
1. 发送buffer队列里包含的TCP/IP header数目超过一定数量
2. 超时(最新版本默认为2毫秒)
如果在线连接只有一个且吞吐量比较高,复制给测试系统后,由于header of line blocking阻塞,会不满足第一个发送条件,导致tcpcopy延后接收到响应数据包的TCP/IP header,速度就跟在线不匹配。
这时可以采用下面两种方案:
1. intercept采用./configure --disable-combined
2. tcpcopy加上参数'-W'
4.2.8 内网和外网特征
TCPCopy运行在内网环境,在设计方面需考虑如下细节:
1. 利用在线数据包本身隐含的网络延迟保持外网特性
2. 利用内网的优质网络特性
同网段机器一般不需要拥塞控制,因此TCPCopy内部可以不考虑拥塞控制
4.3 伪造技术
欺骗测试服务器,需考虑下面细节:
4.4 模拟上层应用交互行为
应用交互有如下特征:
4.4.1 案例1
我们以下面TCP交互图为例:
客户端(Client)采用pipeline技术连续发送三个请求到服务器(Server)。服务器首先对第一个请求做了处理,并发送相应的响应1给客户端。客户端TCP对响应1进行了ack确认。服务器端继续处理请求2,并发送相应的响应2给客户端,接着服务器处理请求3,又发送相应的响应3到客户端。客户端TCP对这两个响应进行了ack确认(合并确认)。
对于TCPCopy,看到的数据包如下图:
这里TCPCopy只关注客户端方向的数据包。
假设在线服务器应用和测试服务器应用配置一样。
如何根据客户端方向的数据包来判断上层应用TCP交互呢?
这里关键信息都隐含在sequence(x)、ack sequence(y)和payload上。
上图前面三个数据包ack sequence都是y1,说明中间没有服务器响应。TCPCopy捕获到这三个数据包,可以立即发送到测试服务器。第四个数据包的sequence(x)和ack sequence(y)跟前面数据包都不一样,说明第三个和第四个数据包中间有服务器端响应。
TCPCopy捕获到第四个数据包,判断出在线服务器已经有响应返回给客户端,如果TCPCopy已经收到测试服务器的响应超过一定时间,则可以发送第四个数据包到测试服务器,否则只能等待。第四个数据包TCP/IP header信息中数据包payload长度等于0,是ack确认数据包。
第四个和第五个数据包sequence(x)一样,而ack sequence(y)不一样,且payload为0,说明第五个是ack确认数据包,如果TCPCopy已经收到测试服务器的响应超过一定时间,则可以发送到测试服务器,否则只能等待。
通过序列号和应用payload长度信息,利用应用相似性,基本可以判断上层应用的TCP交互过程,从而为TCPCopy复制上层应用请求打下基础。
4.4.2 案例2
假设在线服务器应用和测试服务器应用配置一样。
下图是TCPCopy捕获到的数据包,如何回放到测试服务器呢?
下图展示了TCPCopy如何根据序列号判断在线服务器响应(图中虚线)。根据相似性,TCPCopy认为测试服务器也会有相似的响应返回给客户端。
TCPCopy遇到客户端方向的第三个数据包时,由于ack sequence(y2)跟第二个ack sequence(y1)不同,判断出在线服务器有响应。这时TCPCopy已经收到测试服务器的响应超过一定时间,则可以继续发送第三个数据包,否则只能等待。第三个数据包是新的请求还是ack 确认数据包,可以通过TCP/IP header隐含的payload长度得到(这里payload长度等于0,则代表ack确认)。
第四个数据包和第三个数据包sequence(x)相同,而ack sequence(y)不同,且payload长度大于0,则第四个数据包被判断为带有ack确认的新请求。这时TCPCopy已经收到测试服务器的响应超过一定时间,那么可以继续发送第四个数据包,否则只能等待。
客户端第五个数据包ack sequence(x)跟第四个数据包ack sequence(x)不一样,且payload为0,则说明第五个数据包是ack确认数据包。这时TCPCopy已经收到测试服务器的响应超过一定时间,那么可以继续发送第五个数据包,否则只能等待。
第六个数据包根据类似判断方法,可以判断出是ack确认数据包,这时TCPCopy已经收到测试服务器的响应超过一定时间,就可以发送给测试服务器,否则只能等待。
为什么TCPCopy只关注客户端方向的数据包呢?有下面几个原因:
5、应用范围
TCPCopy是在TCP层模拟上层应用交互行为,不会去解析上层协议,因此利用tcpcopy时,需要注意如下事项:
我们在开发服务器应用的时候,利用TCPCopy对广告投放系统(采用了HTTP协议+私有协议)、Nginx HMUX开发(HTTP协议 + HMUX协议)、MySQL协议进行了流量复制。TCPCopy帮助我们发现各种问题的同时,也带给我们开发不少的乐趣,因为利用TCPCopy可以做各种高并发试验。
TCPCopy具体应用范围大致有如下方面:
1. 性能测试
2. 模拟试验
3. 稳定性测试
4. 冒烟测试
5. 极限测试
6. cache预热
7. 功能测试
这些将在下面具体讲述。
5.1 性能测试
利用TCPCopy进行性能测试,可以更好地去发现系统的瓶颈,这主要得益于如下因素:
1. 真实的请求
2. 网络延迟模拟,使得并发更加接近在线的并发
3. TCPCopy的高效
在性能测试案例方面,可以参考。
5.2 模拟试验
将在线流量复制给测试集群,可以做各种容灾试验。例如一台MySQL挂了,测试集群是不是仍然可用。拥有流量的模拟试验更加接近在线情况,各种问题也更容易暴露出来。
5.3 稳定性测试
在开发数据库中间件的时候,利用TCPCopy复制MySQL流量到测试系统,查看长期运行是否稳定,有没有内存泄漏等情况。
一般稳定性测试,运行一个月甚至好几个月。
5.4 冒烟测试
上线项目之前,利用TCPCopy复制流量到测试系统,查看系统是否会出问题,确保上线尽量少出问题。我们开发的系统在上线过程中不出非功能性问题,第一功劳归于TCPCopy。
5.5 极限测试
利用在线环境和测试环境的巨大差异,复制在线流量到测试系统,可以充分暴露潜在的问题。
在开发数据库中间件Cetus的时候,测试环境极为简陋,而在线环境配置比较好。利用TCPCopy发现了大量极端情况下的bug,解决了这些bug后,应用可以更好的去应对在线可能遇到的流量冲击。
5.6 cache预热
可以利用TCPCopy复制请求到cache预热系统,这样可以防止雪崩事件的发生。
5.7 功能测试
对于压力很小的场景,可以利用tcpdump把请求都录下来,然后利用TCPCopy进行离线回放。功能测试,需要在应用层检测TCPCopy回放的效果。
我们在下面应用中利用TCPCopy进行了功能测试:
1. 开发Nginx HMUX模块的时候,检测功能是否正常
2. 开发TCPCopy的时候,查看TCPCopy能否能够复制所有请求到测试服务器中去
如果有请求丢失,说明TCPCopy处理有问题
6、TCPCopy如何运行?
6.1 测试服务器
在测试服务器设置路由,具体参考下图:
6.2 辅助服务器
在辅助服务器运行intercept,具体参考下图:
6.3 在线服务器
在线服务器运行tcpcopy命令,具体参考下图:
6.5 如何查看复制效果?
在线请求数据包方面:
syn cnt:xxx 抓到了多少在线syn数据包
all clt:xxx 抓到了多少在线数据包
clt cont:xxx 抓到了多少带有payload的在线数据包
复制转发数据包方面:
send:xxx 发送了多少数据包给测试服务器
send content:xxx 发送了多少带有payload的数据包给测试服务器
响应方面:
conns:xxx 已经成功建立了多少连接
resp:xxx 收到了多少响应包
c-resp:xxx 收到了多少带有payload的响应包
下图展示了如何查看TCPCopy日志文件中的统计信息。
7、TCPCopy有哪些configure选项?
常用的options选项如下:
8、影响TCPCopy的因素有哪些?
影响TCPCopy运行的因素如下几个方面:
1) 抓包接口
2) 发包接口
3) 去往测试服务器的路上
4) 测试系统OS
5) 测试服务器的应用程序
6) 辅助服务器
8.1 抓包接口
对于抓包,在线压力不能过大,否则TCPCopy效率会非常低,会一直忙于抓包。
如果在线压力大,可以考虑先采用交换机镜像的方式来复制流量到测试集群,然后再运行TCPCopy。
在线机器上抓请求数据包,默认采用raw socket input接口,也可以通过configure指定采用pcap接口。
pcap抓包的好处有如下方面:
1. 可以充分发挥pcap库的内核过滤功能,理论上能够极大地提高抓包的效率
2. 强大的PF_RING、DPDK等机制的支持
需要注意的是,采用pcap接口抓数据包的方式,在某些场合,效果不如raw socket抓数据包的方式,因此最好配合PF_RING或者DPDK,以降低丢包率。
8.2 发包接口
发包默认采用了raw socket output接口,还可以通过pcap(--pcap-send)来发包。压力比较大的场合推荐使用pcap来发包,因为据我们测试,利用pcap发包, tcpcopy性能可以提升30%以上。pcap发包具体可以参考"" 。
发包需注意如下内容:
tcpcopy默认发送的数据包大小为1500(MTU),如果系统网卡MTU设置小于1500,则会导致这些数据包发送不出去,请设置tcpcopy相应的'-M'参数,以匹配系统MTU值。
8.3 去往测试服务器的路上
首先说明一点:虚拟机环境下,跨机器等同于非虚拟环境下的跨网段;同机器等同于非虚拟环境下的同网段。
tcpcopy发送请求数据包以后,如果跨网段(虚拟机环境下,跨机器)的话,路途可能不会一帆风顺,因为被复制的数据包的源IP地址还是原先客户端的IP地址(这是为了引入在线复杂性,不会主动去改变数据包的源IP地址),可能会造成中途设备程序认为这些数据包是非法的或者是伪造的数据包,将tcpcopy转发的数据包给丢弃掉。这时候,在测试服务器端利用tcpdump来抓包,将不会抓到任何复制转发过来的请求数据包(包括三次握手的数据包等)。你可以进一步在同一网段(虚拟机的环境下,同机器)试验一下,如果同网段(虚拟机的环境下,同机器)复制转发成功而跨网段(虚拟机的环境下,跨机器)复制转发不成功,那么跨网段(虚拟机的环境下,跨机器)转发出去的数据包应该在中途被丢弃掉了。
如果跨网段(虚拟机的环境下,跨机器)请求复制不过去,解决策略有两个:
1. 先复制请求到本网段(虚拟机环境下,同机器)的应用代理,通过应用代理再把请求传递给跨网段的测试服务器(虚拟机环境下,跨机器)。
2. 通过-c参数指定IP地址,用以改变源IP地址为合法的IP地址,这样一般就能够通过中途设备程序。
8.4 测试系统OS
8.5 测试服务器的应用程序
并不是每个请求过去,测试服务器上的应用程序都能够及时处理或者都能处理。
应用丢请求的情况归纳如下:
1. 有可能触发了应用程序的bug,导致请求迟迟没有响应
2. 应用程序的协议不支持tcpcopy提前发送请求(类似pipeline形式的请求)
例如有些应用仅仅处理socket buffer中的第一个请求
8.6 辅助服务器
如果辅助服务器设置了IP_FORWARD,那么意味着测试服务器的路由设置没有意义。
路由给辅助服务器后,这些响应包还是往真正的客户端方向走,可能引起客户端发送reset数据包到测试服务器,从而干扰测试的进行。
本文暂时没有评论,来添加一个吧(●'◡'●)