nginx流量复制

需求:将线上平台的流量转发到其它环境中

​ 本文讲述如何通过nginx,将线上平台的流量请求拷贝到其它环境,默认线上平台与其它平台的网络互通。内外网互通查看frp教程。

  1. 在nginx(1.13.4)以上版本中,支持mirror 模块,因此需下载正确版本的nginx。下载地址
  2. 修改nginx配置

配置mirror流量

在普通的location配置中增加一行mirror配置,这代表所有/api的请求都会复制一次到/mirror1,如果要复制很多,那就加很多行mirror就可以了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
location /api {
mirror /mirror1; #镜像
#mirror /mirror2; #镜像
#mirror /mirror3; #镜像
proxy_set_header Host $host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_buffering off;
rewrite ^/api/(.*)$ /$1 break;
proxy_pass http://fas_starter_server;
proxy_read_timeout 600000s;
}

然后,开始配置mirror的location,这里的location与普通的location可配置项一致,没有区别。这里表示上面的流量复制mirror在这里被处理。注意:这里location需要与上面的location在同一个server里面。

internal表示当前location是个内部请求,只有nginx内部才能访问,例如:用户请求 http://xxx.com/mirror1是无法访问的。

proxy_pass配置时,需要指明$request_uri,因为流量复制过来之后会丢掉request_uri参数。即:正常情况下请求http://xxx.com/api/user,剔除前缀路径后,proxy_pass会转发到http://xxx.com/user。但是在这里,只会转发到http://xxx.com,因此需要手动添加request_uri参数。

proxy_pass其实已经可以转发到任何地方了,但是因为有时需要记录日志,而又想将mirror的日志与正常的日志区分开,这需要重新在nginx的server中配置日志路径,因为这里在location中配置日志是无效的。可以看到,下面是配置了http://127.0.0.1:12001$request_uri,又请求了一次nginx。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 复制的流量转发到这里
location = /mirror1 {
internal;
# $request_uri 需要显示指明,因为流量复制过来之后会丢掉request_uri
# 转发到server用于记录日志
proxy_pass http://127.0.0.1:12001$request_uri;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $remote_addr;
}
# 第二个复制
location = /mirror2 {
internal;
proxy_pass http://127.0.0.1:12002$request_uri;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $remote_addr;
}

区分mirror的流量日志

以下配置mirror流量日志,每个mirror就是一个server,可以分别管理。到了这一步,可以理解为mirror的流量就是用户的真实请求,按正常配置即可。这里的proxy_pass转发到http://127.0.0.1:12010,是因为当前nginx是在docker容器中,且需要转发到内网环境,因此在nginx容器安装了frp客户端,经过认证后流量转发到了内网环境。参考frp如何安全暴露内网服务

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
# 流量复制到第一个地方
server {
listen 12001;
# 设置自定义请求头
proxy_set_header X-Token "";

# 转发支付接口的流量
location ~ ^/api/(pay/callback/alipay|pay/callback/wechat|account/wx/getOfficialOpenId) {
access_log /var/log/nginx/mirror_access.log; # 配置成功日志
error_log /var/log/nginx/mirror_error.log; # 配置失败日志
proxy_pass http://127.0.0.1:12010; #转发到真正的服务 如:http://domain.com;
}
}

# 流量复制到第二个地方
server {
listen 12002;
proxy_set_header X-Token "";

# 转发支付接口的流量
location ~ ^/api/(pay/callback/alipay|pay/callback/wechat|account/wx/getOfficialOpenId) {
access_log /var/log/nginx/mirror_access.log;
error_log /var/log/nginx/mirror_error.log;
proxy_pass http://127.0.0.1:12020;
}
}

结语

​ nginx的mirror可以非常方便的将流量复制到其它环境,而且不用担心mirror后的流量在其它环境报错,影响到正式环境,因为mirror的流量不会处理返回值,也不用担心mirror过多而影响nginx性能。