在上一篇 Go网络抓包、引流工具GoReplay 介绍了Gor的一些基础和实际开发中对 HTTP 流量进行复制,以用于测试、性能监测等用途。而Apache APISIX 是 Apache 软件基金会下的云原生 API 网关,它兼具动态、实时、高性能等特点,提供了负载均衡、动态上游、灰度发布(金丝雀发布)、服务熔断、身份认证、可观测性等丰富的流量管理功能。结合使用 Gor 和 Apisix 可以轻松地实现流量复制,并将其应用于各种场景中。

本篇文章将介绍如何使用 Gor 和 Apisix 实现流量复制,具体包括以下几个部分:

  1. 测试环境介绍
  2. 安装和配置 Gor
  3. 安装和配置 Apisix
  4. 配置 Apisix 的 proxy-mirror 插件
  5. 测试流量复制

测试环境介绍

  1. OS: 两台 Ubuntu 虚拟机(Gateway、Node)

    a. Gateway 安装 ApiSix

    b. Node 安装节点服务

  2. Docker & DockerCompose

安装和配置 Gor

首先,需要在Node上安装 Gor 工具。可以从 Gor 的官网下载相应的二进制文件,然后将其解压到服务器上即可。

# tar xvf gor_1.3.3_x64.tar.gz
# cp gor /usr/local/bin/gor
# sudo chmod +x /usr/local/bin/gor

安装完成后,可以使用以下命令启动 Gor:

# gor version

输出

# Version:1.3.0 

安装和配置 Apisix

ApiSix: 这里使用 DockerCompose安装

git clone https://github.com/apache/apisix-docker.git

cd apisix-docker/example

docker-compose up -d

这个命令会启动 Apisix 并监听在本地的 80 端口。

配置 Apisix 的 proxy-mirror 插件

Apisix 的 proxy-mirror 插件可以用于流量复制。 增加一个路由hello-proxy-mirror, Upstream为Node主机的服务A(端口9696),流量复制到Node主机的服务B(端口9797),其中

  1. host 为 指定镜像服务地址
  2. sample_ratio 镜像请求采样率,本例中为1,表示全量复制
{
  "uri": "/hello",
  "name": "hello-proxy-mirror",
  "methods": [
    "GET",
    "POST",
    "PUT",
    "DELETE",
    "PATCH",
    "HEAD",
    "OPTIONS",
    "CONNECT",
    "TRACE"
  ],
  "plugins": {
    "proxy-mirror": {
      "disable": false,
      "host": "http://192.168.1.101:9797",
      "sample_ratio": 1
    }
  },
  "upstream": {
    "nodes": [
      {
        "host": "192.168.1.101",
        "port": 9696,
        "weight": 1
      }
    ],
    "timeout": {
      "connect": 6,
      "send": 6,
      "read": 6
    },
    "type": "roundrobin",
    "scheme": "http",
    "pass_host": "pass",
    "keepalive_pool": {
      "idle_timeout": 60,
      "requests": 1000,
      "size": 320
    }
  },
  "status": 1
}

这个配置会开启 proxy-mirror 插件,并将其配置为将流量发送到本地的 8080 端口,即 Gor 监听的地址。

测试流量复制

接着可开始测试流量复制。

启动 HTTP 服务A监听9696端口:

python3 -m http.server 9696

正常启动输出

Serving HTTP on 0.0.0.0 port 9696 (http://0.0.0.0:9696/) ...

启动 镜像服务B监听9797端口:

python3 -m http.server 9797

正常启动输出

Serving HTTP on 0.0.0.0 port 9797 (http://0.0.0.0:9797/) ...

启动 Gor 监听在本地的 9797 端口

sudo gor --input-raw :9797 --output-stdout  

此命令将监听镜像服务B端口9797, 将 HTTP 流量输出到控制台

接着,curl测试

curl http://192.168.1.100:80/hello -i

输出

HTTP/1.1 404 File not found
Content-Type: text/html;charset=utf-8
Content-Length: 469
Connection: keep-alive
Date: Sun, 19 Mar 2023 06:55:42 GMT
Server: APISIX/3.2.0

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
        "http://www.w3.org/TR/html4/strict.dtd">
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
        <title>Error response</title>
    </head>
    <body>
        <h1>Error response</h1>
        <p>Error code: 404</p>
        <p>Message: File not found.</p>
        <p>Error code explanation: HTTPStatus.NOT_FOUND - Nothing matches the given URI.</p>
    </body>
</html>

测试会发送一个 HTTP 请求到Apisix开放的Http端口80,可以到达下游服务(Node主机的ServerA 9696端口),输出如下:

192.168.1.100 - - [19/Mar/2023 06:47:44] code 404, message File not found
192.168.1.100 - - [19/Mar/2023 06:47:44] "GET /hello HTTP/1.1" 404 -

而且,ApiSix Proxy Mirror复制Http请求到端口 9797的镜像服务, 输出如下:

192.168.1.100 - - [19/Mar/2023 06:49:07] code 404, message File not found
192.168.1.100 - - [19/Mar/2023 06:49:07] "GET /hello HTTP/1.1" 404 -

可见和目标服务的的完全一致。 接着,观察Gor是否正常记录http请求,正常输出如下:

1 af0c2645c0a801c7399d6efb 1679212462567906772 0
GET /hello HTTP/1.1
Host: 192.168.1.100
Connection: close
User-Agent: curl/7.64.1
Accept: */*

说明Gor已经成功从镜像服务捕获流量。 再结合使用Gor的流量回放功能可以应用于例如测试、性能监测等场景。 以上。

参考

本文简要介绍Go网络抓包、引流工具GoReplay。

前言

在后端的实际开发中,会遇到以下一些场景:

  • 用户通过作弊手段绕过前端,利用抓包,进行破解,模拟,魔改交互数据进行伪装。后端程序需要对其操作记录进行重现和跟踪。
  • 某个bug在测试环境无法复现。
  • 服务压测数据和线上数据有偏差,压测数据希望能和线上接近 。

GoReplay是Go语言编写的流量回放工具,侦听器服务器捕获http流量并将其发送到重放服务器或保存到文件。重播服务器将流量转发给给定的地址。

安装

测试环境: Windows。 版本: Version:1.3.0 安装分2步骤:

  1. 前置条件: 安装npcap https://npcap.com

GoReplay可以在Windows机器上工作,但由于Windows堆栈的不同网络层的性质,它有一些细节。 默认情况下,Windows不像Unix系统那样有支持包捕获的网络驱动程序,如果您想捕获通信量,则必须单独安装它。其中一个选项是安装https://nmap.org/npcap/。

  1. 安装:这里测试使用的是 gor-1.3.3_windows.zip https://github.com/buger/goreplay/releases 下载解压即可。

捕获流量

启动两个http服务:

  1. httpServerA: http://localhost:8000 监听端口8000
  2. httpServerB: http://localhost:8001 监听端口8001

路由为 “get: “/helloworld/{name}”

监听端口8000,并输出到stdout

 ./gor --input-raw :8000 --output-stdout

打开浏览器请求接口 http://localhost:8000/helloworld/lilei

在gor的命令行窗口:

1 db0a1f4000000001c344a1d3 1668261985986369000 0
GET /helloworld/lilei HTTP/1.1
Host: localhost:8000
Connection: keep-alive
sec-ch-ua: " Not A;Brand";v=" 此处省略一些系数
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: none
此处省略一些参数

可见,gor已经把整个http请求的完整信息记录下来。 同时gor还支持输出到文件和ElasticSearch,进行回放和分析。记录到文件request.gor

 ./gor --input-raw :8000 --output-file request.gor --input-raw-track-response --input-raw-override-snaplen

打开浏览器请求接口 http://localhost:8000/helloworld/hanmeimei

写入到文件 request_0.gor

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ---- 
-a----        2022/11/12     21:36           1876 request_0.gor

request_0 内容如下:

1 d4571f4000000001b7adc1a6 1668260139796335000 0
GET /helloworld/lilei HTTP/1.1
Host: localhost:8000
Connection: keep-alive
sec-ch-ua: " Not A;Brand";v="99", 此处省略一些参数
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64), 此处省略一些参数
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: none
此处省略一些参数


🐵🙈🙉
2 d4571f4000000001b7adc1a6 1668260139796652000 0
HTTP/1.1 200 OK
Content-Type: application/json
Date: Sat, 12 Nov 2022 13:35:39 GMT
Content-Length: 25

{"message":"Hello lilei"}
🐵🙈🙉
1 d4571f4000000001b7adc22b 1668260148757949000 0
GET /helloworld/hanmeimei HTTP/1.1
Host: localhost:8000
Connection: keep-alive
sec-ch-ua: " Not A;Brand";v="99", 此处省略一些参数
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) , 此处省略一些参数
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: none
此处省略一些参数


🐵🙈🙉
2 d4571f4000000001b7adc22b 1668260148758268000 0
此处省略一些参数

{"message":"Hello hanmeimei"}
🐵🙈🙉

流量回放

接着将该文件request_0.gor 进行流量回放,并转发到另外一台服务器(HttpServerB)上:

./gor --input-file request_0.gor --output-http http://localhost:8001

观察HttpServerB服务器控制台输出:

INFO ts=2022-11-12T21:37:26+08:00 caller=greeter.go:44 service.id=LAPTOP-H3HBMV8A service.name= service.version= trace.id= span.id= msg=CreateGreeter: lilei
INFO ts=2022-11-12T21:37:34+08:00 caller=greeter.go:44 service.id=LAPTOP-H3HBMV8A service.name= service.version= trace.id= span.id= msg=CreateGreeter: hanmeimei

从日志中可以看到两个请求(http://localhost:8000/helloworld/ilei、http://localhost:8000/helloworld/hanmeimei)分别重放请求到了HttpServerB。

gor支持进行流量缩小、放大、倍速重放,实现真实流量的压测效果。 更多命令 ./gor -help 查看

参考

jefffff

Stay hungry. Stay Foolish COOL

Go backend developer

China Amoy