正文
最近做功能重构,在上线前要求验证重构后的代码与老代码实现逻辑是否一致,基于这个需求,需要在生产环境做一个功能将生产服务器上的流量复制一份发送到测试服务器上。
就这个事情这几天考察了三种技术,1. 基于 nginx+lua 脚本,2. tcpcopy,3. gor。这里大概说一下这三种方案:
这种方案的思路是在生产服务器前端架一层壳子,将请求拦截,然后基于 lua-nginx-module 模块,写 lua 脚本,使用其内置的 ngx.location.capture_multi ,对后端发起多个异步并发请求,然后统一将结果返回给前端。
该方案需要安装 nginx ,以及依赖 lua-nginx-module ,ngx_devel_kit 等模块,然后需要写lua代码来复制请求。
这种方案是工作在网络等 TCP 和 IP 层做请求复制,因为其间架构调整过两次,现在的实现架构是在生产环境启动 tcpcopy 进程,测试环境启动 intecept 进程,然后配置复制请求的路径。
这是今天搜到的用 Go 语言写的工具,在生产服务器上安装一个 tar 包,用 root 权限启动命令即可
1的方案安装步骤较多,需要理解 nginx 处理请求的过程和 lua 脚本语法以及相关请求调用的 API 。2的安装简单一些,只需要在生产和测试服务器分别安装 tcpcopy 和 intecept 即可(当然前提是他们依赖的 libpcap 之类也有了,否则也要安装),然后启动命令加参数即可,但由于该方案工作在较为底层,看起来比较重,实际跑了个例子就没继续研究。3安装最简单,下载一个 tar 包,解压,sudo 执行即搞定。
个人比较倾向于3,所以这里就介绍一下gor的实现方式。
-
下载
根据操作系统环境下载安装包 https://github.com/buger/gor/releases,建议选择 master 分支的,我的是 Mac ,所以选择了 tar 包
-
解压
tar -xvf gor_v0.14.1_mac.tar.gz
-
验证
sudo ./gor --input-raw :8080 --output-http http://192.168.22.33:8080
至此就搞定了,简单吧!!!
这条命令是监控本地的 8080 端口,并实时复制请求到需要 192.168.22.33 的 8080 端口上,需要本地 root 执行权限。
下面是我的扩展用法:
-
保存请求到文件
sudo ./gor --input-raw :8080 --output-file requests.gor
这里将 8080 端口的请求保存到本地文件上,可以用于线上请求记录之后的功能回放
-
根据文件回放请求
sudo ./gor --input-file requests.gor --output-http http://192.168.22.33:8080
将上面保存的文件请求回放到 192.168.22.33 服务器的 8080 端口上
-
url 过滤
包含 /order 的 URL 才发送请求
sudo ./gor --input-raw :8080 --output-http http://192.168.22.33:8080 --http-allow-url ^/order.
-
url 过滤+记录文件+请求回放
sudo ./gor --input-raw :8080 --output-file gor-order-requests.gor --output-http http://192.168.22.33:8080 --http-allow-url ^/order.
sudo ./gor --input-file gor-order-requests.gor --output-http http://192.168.22.33:8080
-
url 过滤+记录文件+记录响应
sudo ./gor --input-raw-track-response --input-raw :8080 --output-file gor-order-request-response.gor --http-allow-url ^/order.
下面是别人整理的一些详细配置说明,可以参考一下
-cpuprofile string
write cpu profile to file
-debug verbose
打开debug模式,显示所有接口的流量
-http-allow-header value
用一个正则表达式来匹配http头部,如果请求的头部没有匹配上,则被拒绝
gor --input-raw :8080 --output-http staging.com --http-allow-header api-version:^v1 (default [])
-http-allow-method value
类似于一个白名单机制来允许通过的http请求方法,除此之外的方法都被拒绝.
gor --input-raw :8080 --output-http staging.com --http-allow-method GET --http-allow-method OPTIONS (default [])
-http-allow-url value
一个正则表达式用来匹配url, 用来过滤完全匹配的的url,在此之外的都被过滤掉
gor --input-raw :8080 --output-http staging.com --http-allow-url ^www. (default [])
-http-disallow-header value
用一个正则表达式来匹配http头部,匹配到的请求会被拒绝掉
gor --input-raw :8080 --output-http staging.com --http-disallow-header "User-Agent: Replayed by Gor" (default [])
-http-disallow-url value
用一个正则表达式来匹配url,如果请求匹配上了,则会被拒绝
gor --input-raw :8080 --output-http staging.com --http-disallow-url ^www. (default [])
-http-header-limiter value
读取请求,基于FNV32-1A散列来拒绝一定比例的特殊请求
gor --input-raw :8080 --output-http staging.com --http-header-imiter user-id:25% (default [])
-http-original-host
在--output-http的输出中,通常gor会使用取代请求的http头,所以应该禁用该选项,保留原始的主机头
-http-param-limiter value
Takes a fraction of requests, consistently taking or rejecting a request based on the FNV32-1A hash of a specific GET param:
gor --input-raw :8080 --output-http staging.com --http-param-limiter user_id:25% (default [])
-http-rewrite-url value
Rewrite the request url based on a mapping:
gor --input-raw :8080 --output-http staging.com --http-rewrite-url /v1/user/([^\/]+)/ping:/v2/user/$1/ping (default [])
-http-set-header value
Inject additional headers to http reqest:
gor --input-raw :8080 --output-http staging.com --http-set-header 'User-Agent: Gor' (default [])
-http-set-param value
Set request url param, if param already exists it will be overwritten:
gor --input-raw :8080 --output-http staging.com --http-set-param api_key=1 (default [])
-input-dummy value
Used for testing outputs. Emits 'Get /' request every 1s (default [])
-input-file value
从一个文件中读取请求
gor --input-file ./requests.gor --output-http staging.com (default [])
-input-http value
从一个http接口读取请求
gor --input-http :9000 --output-http staging.com (default [])
-input-raw value
Capture traffic from given port (use RAW sockets and require *sudo* access):
gor --input-raw :8080 --output-http staging.com (default [])
-input-tcp value
用来在多个gor之间流转流量
gor --input-tcp :28020 --output-http staging.com (default [])
-memprofile string
write memory profile to this file
-middleware string
Used for modifying traffic using external command
-output-dummy value
用来测试输入,打印出接收的数据. (default [])
-output-file value
把进入的请求写入一个文件中
gor --input-raw :80 --output-file ./requests.gor (default [])
-output-http value
转发进入的请求到一个http地址上
gor --input-raw :80 --output-http http://staging.com (default [])
-output-http-elasticsearch string
把请求和响应状态发送到ElasticSearch:
gor --input-raw :8080 --output-http staging.com --output-http-elasticsearch 'es_host:api_port/index_name'
-output-http-redirects int
设置多少次重定向被允许
-output-http-stats
每5秒钟输出一次输出队列的状态
-output-http-timeout duration
指定http的request/response超时时间,默认是5秒
-output-http-workers int
gor默认是动态的扩展工作者数量,你也可以指定固定数量的工作者
-output-tcp value
用来在多个gor之间流转流量
gor --input-raw :80 --output-tcp replay.local:28020 (default [])
-output-tcp-stats
每5秒钟报告一次tcp输出队列的状态
-split-output true
By default each output gets same traffic. If set to true it splits traffic equally among all outputs.
-stats
打开输出队列的状态
-verbose
Turn on more verbose output
当然最好的还是直接关注作者的 git 项目:https://github.com/buger/gor/wiki