go replay流量重放[详细教程]
go replay流量重放[详细教程]
一、介绍
- Goreplay 是用 Golang 写的一个 HTTP 实时流量复制工具。功能更强大,支持流量的放大、缩小,频率限制,还支持把请求记录到文件,方便回放和分析,也支持和 ElasticSearch 集成,将流量存入 ES 进行实时分析。
- GoReplay 不是代理,而是监听网络接口上的流量,不需要更改生产基础架构,而是在与服务相同的计算机上运行 GoReplay 守护程序。
Github地址:https://github.com/buger/goreplay
二、安装
进入官网下载对应操作系统版本,下载后解压即可使用
这里选择最新的v1.3.3为例:https://github.com/buger/goreplay/releases/download/1.3.3/gor_1.3.3_mac.tar.gz
下载完后可直接执行使用
三、参数讲解
1. 具体参数
# 查看帮助文档
./gor --help
常用参数:
–input-raw :用来捕捉http流量,需要指定ip地址和端口
–input-file :接收流量
–output-file:保存流量的文件
–input-tcp:将多个Goreplay实例获取的流量聚集到一个Goreplay实例
–output-stdout:终端输出
–output-tcp:将获取的流量转移至另外的Goreplay实例
–output-http:流量释放的对象server,需要指定IP地址和端口
–output-file:录制流量时指定的存储文件
–http-disallow-url :不允许正则匹配的URL
–http-allow-header :允许的Header头
–http-disallow-header:不允许的Header头
–http-allow-method:允许的请求方法,传入值为GET,POST,OPTIONS等
–input-file-loop:无限循环,而不是读完这个文件就停止了
–output-http-workers:并发请求数
–stats --out-http-stats 每5秒输出一次TPS数据(查看统计信息)
–split-output true: 按照轮训方式分割流量
–output-http-timeout 30s:http超时30秒时间设置,默认是5秒
2. 案例demo
- 如果是性能测试,可以不考虑请求的顺序和速率,并且要求无限循环
# --input-file 从文件中获取请求数据,重放的时候 100x 倍速
# --input-file-loop 无限循环,而不是读完这个文件就停止
# --output-http 发送请求到 http://host2.com
# --output-http-workers 并发 100 发请求
# --stats --output-http-stats 每 5 秒输出一次 TPS 数据
./goreplay --input-file 'request.gor|10000%' --input-file-loop --output-http 'http://host2.com' --output-http-workers 100 --stats --output-http-stats
- 抓取80端口的HTTP请求,只抓取URL是/api/v1的,并输出到终端
./goreplay --input-raw :80 --http-allow-url '/api/v1' --output-stdout
- 抓取80端口的所有请求,并保存到文件,实际会分批保存为request_0.gor,request_1.gor这种文件名
./goreplay --input-raw :80 --output-file 'request.gor'
- 流量回放到多个站点(复制引流)
sudo ./gor --input-tcp :28020 --output-http "http://staging.com" --output-http "http://dev.com"
- 按照轮训方式分割流量(平分流量)
sudo ./gor --input-raw :80 --output-http "http://staging.com" --output-http "http://dev.com" --split-output true
- HTTP超时设置
gor --input-tcp replay.local:28020 --output-http http://staging.com --output-http-timeout 30s
- 性能测试(表示放大2倍速度来回放)
gor --input-file "requests.gor|200%" --output-http "staging.com"
- 回放速率不超过10QPS(绝对值)
gor --input-tcp :28020 --output-http "http://staging.com|10"
- 回放不超过原流量的10%(百分比,这里是总流量的占比)
gor --input-raw :80 --output-tcp "replay.local:28020|10%"
- 禁止的URL正则(除/api之外的请求)
gor --input-raw :8080 --output-http staging.com --http-disallow-url /api
- 基于方法(表示只允许GET,OPTIONS的请求)
gor --input-raw :80 --output-http "http://staging.server" --http-allow-method GET --http-allow-method OPTIONS
- 基于请求头
gor --input-raw :8080 --output-http staging.com --http-allow-header api-version:^1\.0\d
gor --input-raw :8080 --output-http staging.com --http-disallow-header "User-Agent: Replayed by Gor"
- 重写请求
gor --input-raw :8080 --output-http staging.com --http-rewrite-url /v1/user/([^\\/]+)/ping:/v2/user/$1/ping
- 设置URL参数
gor --input-raw :8080 --output-http staging.com --http-set-param api_key=1
- 设置HEADER
gor --input-raw :80 --output-http "http://staging.server" --http-header "User-Agent: Replayed by Gor" --http-header "Enable-Feature-X: true"
- 导出到ES
./gor --input-raw :8000 --output-http http://staging.com --output-http-elasticsearch localhost:9200/gor
- 基于Header或URL参数值的一致限制
如果您在Header或URL中存储了唯一的用户ID(例如API密钥),则可以仅针对该用户的一部分持续转发指定的流量百分比。基本公式如下:FNV32-1A_hashing(value) % 100 >= chance。例子:
当基于Header或参数进行限制时,仅支持基于百分比的限制
# Limit based on header value
sudo ./gor --input-raw :80 --output-tcp "replay.local:28020|10%" --http-header-limiter "X-API-KEY: 10%"
# Limit based on header value
sudo ./gor --input-raw :80 --output-tcp "replay.local:28020|10%" --http-param-limiter "api_key: 10%"
3. 注意点
- 如果 HTTP 请求不符合规范,可能会抓不到包。遇到过 HTTP 请求头里面的 Content-Length 不等于实际的 Body 大小,goreplay 认为其请求未结束。
- input-file 是单 goroutine 在跑,会有性能瓶颈。测试的时候,读取的 RPS 在 1.7w - 1.8w 左右,如果压测需求大于这个,需要开多个进程同时跑。
- 多个 input 之间是并行的,但单个 input 到多个 output,是串行的。所有 input 都实现了 io.Reader 接口,output 都实现了 io.Writer 接口。所以阅读代码时,input 的入口是 Read() 方法,output 的入口是 Write() 方法。
四、具体使用
前置准备
本地编写http服务并启动,用于模拟线上服务器
勾选goland启动多实例选项,分别启动两个服务:localhost:8888、localhost:9999
- 选中main.go,鼠标右击配置
- 勾选允许多实例运行
- 先执行main.go运行实例1
- 修改暴露的端口,然后再执行main.go,运行实例2
- 最终效果
或者将port端口暴露为参数,将main.go编译为可执行文件,然后分别运行两次。当然也可以直接编写两份一样的main函数,然后改下端口
用法一:本地录制流量保存到文件并回放到指定服务器
- 启动goreplay(gor),执行命令,录制线上流量
#将端口 8888 流量保存到本地的文件
sudo ./gor --input-raw :8888 --output-file=requests.gor
- 通过curl或postman等接口测试工具,访问服务
- 暂停gor,观察录制的流量信息
1 f83d22b80000000169dd18f1 1736750112736464000 0
GET /getInfo HTTP/1.1
User-Agent: Apifox/1.0.0 (https://apifox.com)
Accept: */*
Host: localhost:8888
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
- 回放流量,将流量回放到另一个服务器上
./gor --input-file requests_0.gor --output-http="http://localhost:9999"
用法二:将实时流量输出到控制台
- 执行gor命令录制流量
# 将服务一的实时流量输出到控制台
sudo ./gor --input-raw :8888 --output-stdout
- 通过curl或其他工具访问服务一,并观察控制台打印信息
用法三:将实时流量转发到服务二
- 执行gor命令转发流量
# 将服务一的实时流量转发到服务二
sudo ./gor --input-raw "localhost:8888" --output-http="http://localhost:9999"
- 通过curl或其他工具访问服务一,并观察服务二的请求信息
用法四:压测(流量放大或缩小)
goreplay支持将捕获到的生产实际请求流量减少或者放大重播以用于测试环境的压力测试.压力测试一般针对 Input 流量减少或者放大。
- 执行gor命令进行流量缩放
# 将流量放大为200%,按照两倍速率去回放,比如:之前两个请求间的间隔为2s,我放大两倍后,请求间隔就变为了1s,相当于qps翻倍
# 如果“input-flie”是多个文件,可以用正则去匹配,如“request*.gor|200%”
# 除了input-file可以限流,--output-http也可以限流,详细文章后半部分
sudo ./gor --input-file "requests*.gor|1%" --output-http="http://localhost:9999"
- 通过curl或其他工具访问服务一,并观察服务二的请求信息,观察请求是否有被放大或缩小
goreplay限流详细解释
goreplay支持将捕获到的生产实际请求流量减少或者放大重放以用于测试环境的压力测试,压力测试一般以对input的流量减少或者放大。例如:
# Replay from file on 2x speed
#将请求流量以2倍的速度放大重放;当然也支持10%,20%等缩小请求流量
gor --input-file "requests.gor|200%" --output-http "staging.com"
如果受限于测试环境的服务器的资源压力,只想重放一部分流量到测试环境中,而不需要所有的实际生产流量,那么就可以用限速功能。两种策略实现限流:
- 随机丢弃请求流量
- 基于Header或者URL丢弃一定的流量(百分比)
①随机丢弃请求流量:
input和output两端都支持限速,有两种限速算法,百分比或者绝对值
- 百分比:input端支持缩小或者放大请求流量,基于指定的策略随机丢弃请求流量
- 绝对值:如果单位时间(秒)内达到临界值,则丢弃剩余的请求流量,下一秒临界值还原
详细用法:
在output终端使用”|”运算符指定限速阈值,例如:
- 使用绝对值限速(input端使用绝对值时,则对应QPS)
# staging.server will not get more than ten requests per second
#staging服务每秒只接收10个请求
gor --input-tcp :28020 --output-http "http://localhost:8082|10"
- 使用百分比限速
# replay server will not get more than 10% of requests
# useful for high-load environments
gor --input-raw :80 --output-tcp "replay.local:28020|10%"
②基于Header或者URL参数限速
如果header或者URL参数中有唯一值,例如(API key),则可以转发指定百分比的流量到后端,例如:
# Limit based on header value
gor --input-raw :80 --output-tcp "replay.local:28020|10%" --http-header-limiter "X-API-KEY: 10%"
# Limit based on URL param value
gor --input-raw :80 --output-tcp "replay.local:28020|10%" --http-param-limiter "api_key: 10%"
五、代码地址
教程代码地址
Github:
https://github.com/ziyifast/ziyifast-code_instruction/tree/main/go-demo/go-replay
参考文档:
https://juejin.cn/post/6999586008698208263
https://blog.csdn.net/qq_40093255/article/details/117227229