流量复制方案对比:Tcpcopy vs Goreplay

文章首发公众号「码农吴先生」, 欢迎关注,及时获取更多技术干活~

「流量复制」经常应用在准生产环境的测试中,将线上的流量复制到一个准生产环境服务中,测试新功能和服务的承压能力。流量复制能够彻底模拟线上的流量,对复杂的业务场景进行真实的服务测试,又不会对生产服务产生任何反作用。python

对于复杂的流量复制应用场景和需求,彻底能够立项开发一套完整的复制架构,可参考字节团队自研的 ByteCopy 项目。而对于一些简单的需求,开源的工具基本能够搞定。开源的流量复制工具备不少,经常使用的有 goreplay、tcpreplay、tcpcopy 等。nginx

本文主要来探讨下 tcpcopy 和 goreplay 的方案实现,废话很少说开整。git

tcpcopy 方案实现

tcpcopy 简介

tcpcopy 由网易技术部王斌等开发,并于 2011 年 9 月开源的。tcpcopy 最新架构以下(来自做者王斌博客:https://blog.csdn.net/wangbin...):github

架构

tcpcopy 主要有两个组件构成 tcpcopy client 和 intercept 。client 端负责复制流量和转发,intercept 负责对回应流量的拦截和 tcpcopy 的连接处理。golang

tcpcopy 搭建

实例环境以下,下面来阐述下整个架构的搭建过程:ubuntu

  • 192.168.33.11 生产服务器,部署 tcpcopy client
  • 192.168.33.12 辅助服务器,部署 intercept
  • 192.168.33.13 测试服务器

各组件可直接从 github 下载源码包,编译安装:bash

# 起压机部署 tcpcopy client 192.168.33.11
wget https://github.com/session-replay-tools/tcpcopy/archive/1.0.0.tar.gz
tar xvf 1.0.0.tar.gz
cd tcpcopy-1.0.0
./configure --prefix=/opt/tcpcopy
make
make install

# 辅助机部署 intercept 192.168.33.12 , 截获包须要依赖 libpcap 抓包函数库
yum -y install libpcap-devel
# ubuntu
# apt install -y libpcap-dev
https://github.com/session-replay-tools/intercept/archive/1.0.0.tar.gz
tar xvf 1.0.0.tar.gz
cd intercept-1.0.0
./configure --prefix=/opt/tcpcopy/
make
make install

安装完以后,先启动 intercept,运行以下命令:服务器

/opt/tcpcopy/sbin/intercept -i enp0s8 -F 'tcp and src port 8000' -d
# -i,指定网卡 enp0s8
# -F,过滤,语法和pcap抓包工具一直,如tcpdump
# -d,以domain的形式启动。
# 其余参数可 -h 查看。

启动 intercept 以后,再启动 tcpcopy client 。tcpcopy 启动依赖 intercept ,启动时确保 intercept 启动成功。网络

/opt/tcpcopy/sbin/tcpcopy -x 8000-192.168.33.13:8000 -s 192.168.33.12 -c 192.168.1.x -n 2 -d
# -x,复制本地8000端口的流量,转发到192.168.33.13机器的8000端口
# -s,辅助服务器intercept 地址
# -c,修改转发包的原地址为该地址段的地址,这里也能够是明确的ip。这个ip端用来假装数据包,方便intercept作路由劫持。
# -n,流量倍数
# -d,以domain的形式运行

在测试服务器添加拦截路由,以下:session

# 测试机 192.168.33.13
route add -net 192.168.1.0 netmask 255.255.255.0 gw 192.168.33.12

该路由至关于把到 192.168.1.0 网段的包都走网关 192.168.33.12,对测试服务器的回包作伪地址拦截。

这即是 tcpcopy 的整个架构部署了。

包流动分析

下面咱们抓包看看这个过程当中包是如何流动的。

我在 tcpcopy client 机器 192.168.33.11 和测试机器 192.168.33.13 使用 python -m SimpleHTTPServer 分别起了一个 8000 端口的服务用来测试,从我本机 192.168.33.1 发送请求,在三台机器上抓包。

tcpcopy client 机器 192.168.33.11 包信息以下:

tcpcopy

红色标注块为我本机(192.168.33.1)和 tcpcopy client 机器(192.168.33.11)的正常请求交换,从三次握手,到 http 请求,到最后的断链。

蓝色标注块则为 tcpcopy 复制的流量,能够看到为了让 intercepter 拦截回包流量,tcpcopy 已将包源 ip 地址替换为咱们指定的伪网段(192.168.1.0)的地址,这样在回包时,就会根据测试服务器上的路由将回包指向辅助服务器 intercept,避免对生产流量形成影响。这也是为何复制流量三次握手和 http 都没有回包的缘由。

看测试服务器 192.168.33.13 的包:

test server

测试服务器的包和正常流量包同样,三次握手到 http 请求,最后断连。这里和测试服务器 192.168.33.13 交互的源地址 ip 已经被 tcpcopy 替换为伪 ip 192.168.1.1 。

看 intercept 192.168.33.12 的包:

image

能够看到辅助服务器拦截下来的请求,标注块 1 为复制流量三次握手时的回包,标注块 2 为 http 请求的回包,这即是 intercept 的拦截功能。能够看到在标注块 一、2 以后,辅助服务器(192.168.33.12)和 tcpcopy 服务器(192.168.33.11)进行了数据交换,这部分即是 intercept 的 tcp 处理功能,它把有用的信息返回给 tcpcopy 以便能使 tcpcopy 和测试机的 tcp 连接完成。

根据上边抓包,咱们获得了和架构图同样的包流动过程,总结以下:

  • 生产流量正常请求,服务正常回应。
  • tcpcopy 服务在生产机器上复制流量,并修改流量包的源 ip 地址为咱们指定的伪网络段(-c 参数指定),以后将流量转发到测试服务器。
  • 测试服务器,接受到流量,但包的源地址为伪网络段的地址,回包时根据提早配置好的伪路由,将回包导流到辅助服务器。
  • 辅助服务器接收测试服务器的回包,可是并不转发。而是解包,只返回部分必要的信息给 tcpcopy,以便完成 tcpcopy 和测试服务器之间的 tcp 交互。

根据官方文档,咱们还须要注意几个问题:

  • 辅助服务器不作包的转发,须要关闭内核参数 ip_forward
  • 在作测试时,注意上行流量的过滤和测试数据源的隔离,防止对生产数据形成屡次操做的影响。
  • 上边为在线实时的复制模式,tcpcopy 还支持离线方式,具体可查阅文档
  • 辅助机须要和测试机在一个网段,以便辅助机做为伪网段的网关使用。这里能够加一次代理,解除这个限制。如使用 nginx 做为测试中起色,将伪路由添加到 nginx 服务器上,测试机只须要向 nginx 注册便可,无需作其余配置。

goreplay 方案实现

goreplay 简介

Goreplay 是另外一个比较经常使用的流量复制开源工具。与 tcpcopy 相比它的架构更简单,只有一个 gor 组件,以下:

image

只须要在生产服务器上启动一个 gor 进程,它负责全部的工做包括监听、过滤和转发。
它的设计遵循 Unix 设计哲学:_一切都是由管道组成的,各类输入将数据复用为输出_。

输入输出一般被成为插件,常见的有下面几种。

可用输入:

  • --input-raw 用于捕获 HTTP 流量,您应该指定 IP 地址或接口和应用程序端口。
  • --input-file 接受流量输出的文件(--output-file),用来离线流量重放。
  • --input-tcp 若是您决定未来自多个转发器 Gor 实例的流量转发给它,则由 Gor 聚合实例使用。

可用输出:

  • --output-http 重放 HTTP 流量到给定的端点,接受基础 URL。
  • --output-file 记录传入的流量到文件。更多关于保存和从文件重播
  • --output-tcp 将传入数据转发给另外一个 Gor 实例,并与其一块儿使用--input-tcp。
  • --output-stdout 用于调试,输出全部数据到 stdout。

你能够对数据进行限速、过滤、从新,还能够重用中间件实现一些自定义逻辑处理,如私有数据的过滤、认证等个性需求。

其余经常使用参数:

  • --output-http "http://staging.com|10" 输出流量的 10%
  • --http-allow-method 根据请求方式过滤。
  • --http-allow-url url 白名单,其余请求将会被丢弃。
  • --http-disallow-url 赶上一个 url 相反,黑名单,其余的请求会被捕获到。

本文不对中间件作过多描述,仅讨论经常使用功能,对中间件有需求的可参考中间件文档

goreplay 搭建

Goreplay 是使用 golang 开发的,咱们能够直接使用编译好的对应各系统的二进制文件,也能够本身编译,咱们这里直接使用二进制文件。

wget https://github.com/buger/goreplay/releases/download/v1.3.0_RC1/gor_1.3_RC1_x64.tar.gz
tar zxvf gor_1.3_RC1_x64.tar.gz
# 解压出二进制文件 gor
gor

接下来,直接启动 gor 便可复制流量和转发。

sudo ./gor --input-raw :8000 --output-http="http://192.168.33.13:8001"

复制本地 8000 端口的流量到 http 远端服务http://192.168.33.13:8001。(复制同端口的流量时,流量会重复。这是 gor 的一个 bug,截止目前 1.3 版本仍可复现,可见issue292)

goreplay 的流量转发,并非直接 tcp 包的转发,而是从新组织 http 协议级别的请求,发送到测试服务器。因此它是新的 gor 线程和测试服务器的交互,和监听线程无关,因此无需对流量进行拦截。

包流向分析

下面咱们来看下 gor 复制的流量包的流向过程:

gor

红色标注块为正常流量,蓝色标注块为复制的流量。

看到此处,你可能会有疑问,为何 gor 不用拦截流量?

你们仔细看 tcpcopy 和 gor 复制流量的端口,在生产机和测试机创建链接时,tcpcopy 虽然修改了 tcp 包的源 ip,但端口仍是用的请求客户端的端口,是 tcp 数据链路层级别的流量复制。而 gor 这里严格来讲并非复制,而是从新构建了 http 请求。使用新端口来和测试机建连,相对的测试机在回包时,即便包是回到了生产机,但因为是和客户端不一样的端口,也不会对生产流量形成影响。

对比总结

到此,咱们对流量复制有了些基本的概念和应用了,也对 tcpcopy 和 goreplay 两款开源工具备了必定的认知。两款开源工具各有优缺点,咱们来一块总结下。

  • tcpcopy 部署架构相对复杂,goreplay 相对简单只需启动一个进程。
  • tcpcopy 支持的协议比较丰富,goreplay 根据架构特色仅支持 http。
  • tcpcopy 和 goreplay 都支持离线和在线录制回放。

简单 http 复制 goreplay 彻底能够胜任,稍复杂点或应用场景更复杂,那么推荐 tcpcopy。更复杂,要求更高的流量复制,那只能咱们本身定制了。

好了,本篇到这结束了,欢迎留言讨论,你觉着最佳流量复制方案。

我是DeanWu,一个努力成为真正SRE的人。

关注公众号「码农吴先生」, 可第一时间获取最新文章。回复关键字「go」「python」获取我收集的学习资料,也可回复关键字「小二」,加我wx拉你进技术交流群,聊技术聊人生~
相关文章
相关标签/搜索