背景
公司让调研流量回放工具goreplay,实现部分能力,其中包括要统计线上业务还在使用的api(代码陈旧,俗称屎山,无法从代码层面去做),我这里就使用goreplay来实现,先说说如何将线上环境接入goreplay。
接入
goreplay仓库地址
我这里采用类sidecar形式去做,这样不会影响原业务容器,goreplay本身也是这样的设计
制作容器
为什么要自己制作容器,不用官方已经做好的?因为后面使用的时候发现需求有出入,goreplay无法满足需求,需要对源码进行一点修改,然后自行编译二进制文件来制作容器
Dockerfile如下
1
2
3
4
5
|
FROM alpine:latest
ADD ./gor /gor
ENV INPUT :80
ENV OUTPUT https://example.com/api/goreplay
CMD ["sh", "-c", "/gor --input-raw $INPUT $OUTPUT"]
|
描述文件如下(精简后)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: service
name: service
namespace: service
spec:
replicas: 1
selector:
matchLabels:
app: service
template:
metadata:
labels:
app: service
spec:
containers:
- env:
...省略
image: service:2024-01-15-17-58-26
imagePullPolicy: IfNotPresent
name: service
...省略
- env:
- name: INPUT
value: ":80"
- name: OUTPUT
value: "https://example.com/api/goreplayHanddle"
image: registry-vpc.cn-hangzhou.aliyuncs.com/zhangjinhui/gor:sidecar
imagePullPolicy: IfNotPresent
name: admin-service
|
启动后即可
实现URL转换
在使用官方的最新版1.3.0时(截至目前已停止更新),发现,在使用output-http回放流量时,request请求进来的PATH,是我配置的OUTPUT的PATH,根据上面描述文件,回放后,path变为了:/api/goreplayHanddle, 这样我无法根据回放流量获取原始的PATH路径了,在翻阅Issue后找到862, 内容跟我并没有什么关系,但是我发现可以根据该段代码自行修改发挥,从而可以实现我的需求。
思路
1
2
3
4
5
6
7
|
// fix #862
if c.config.url.Path == "" && c.config.url.RawQuery == "" {
req.URL.Scheme = c.config.url.Scheme
req.URL.Host = c.config.url.Host
} else {
req.URL = c.config.url
}
|
源码中逻辑为,如果配置的output-http中包含path内容,则直接将配置URL全部作为回放URL,如果配置中没有PATH内容,则只采用Scheme和Host回放,Path则使用原始的req的path进行回放,此时就出现了问题,因为我既想要配置自定义的path用来方便我收集回放流量,又要原始path进行后续处理,于是将该段代码修改为:
1
2
3
4
5
6
7
8
9
|
// fix #862
if c.config.url.Path == "" && c.config.url.RawQuery == "" {
req.URL.Scheme = c.config.url.Scheme
req.URL.Host = c.config.url.Host
} else {
req.URL.Scheme = c.config.url.Scheme
req.URL.Host = c.config.url.Host
req.URL.Path = c.config.url.Path + req.URL.Path
}
|
我将自己配置的path和req原始path拼接,获得了一个以"/api/goreplayHanddle"开头的path,这样我自己写一个接口就可以收集所有回放的流量,然后再进行其他处理,在我的处理逻辑中,我再将前缀去除:
1
|
url := strings.ReplaceAll(c.Ctx.Request.URL.String(), "/api/goreplayHanddle", "")
|
这样我就得到了原始的URL,以此实现我的需求。
下面是整个过程。
拉源码
1
|
git clone https://github.com/buger/goreplay.git
|
修改代码
就是修改上面部分
编译
编译前需要先制作环境容器,在仓库中有一个Dockerfile.dev文件,直接将他build出来,起名为gor-amd64:latest,因为makefile中使用的是这个名字
1
|
docker build -t gor-amd64:latest -f Dockerfile.dev .
|
随后开始编译
1
|
make release-linux-amd64
|
完成之后在当前目录下就会生成一个gor名字的文件,再经上文制作容器后即可进行使用。
效果
目前自己的api只是将部分request内容转存到mysql,还没有做去重、分类等等需求,后面慢慢做。
