nginx 流量镜像

#nginx 流量镜像 官网插件说明地址
#http://nginx.org/en/docs/http/ngx_http_mirror_module.html
 
#The ngx_http_mirror_module module (1.13.4) implements mirroring of an original request by creating background mirror subrequests. Responses to mirror subrequests are ignored.
#我们可以这样理解nginx镜像,mirror本意是镜子镜像的意思,故可以理解好比一个镜像站点,将所有的请求都收集起来,这个镜像就代表了所有真实有效的原始请求。有了这些原始请求,后续我们可以将请求引流其它环境的服务去中,比如到线上测试环境。这个过程就实现了线上流量复制。
 
#nginx_mirror_module 模块可用于以下几个场景:
验证服务是否正常以及服务的性能;
复制真实流量实现服务验证,不必造数据,不影响线上正常访问;
与灰度发布不同,镜像流量不会影响真实流量;
以真实流量排查线上问题;
重构 —— 重构场景下,用真实流量检验重构系统;
 
Example Configuration
官网配置说明
 
location / {
    mirror /mirror;
    proxy_pass http://backend;
}
 
location = /mirror {
    internal;
    proxy_pass http://test_backend$request_uri;
}
 
Directives
Syntax: mirror uri | off;
Default:   
mirror off;
Context:    http, server, location
Sets the URI to which an original request will be mirrored. Several mirrors can be specified on the same configuration level.
 
Syntax: mirror_request_body on | off;
Default:   
mirror_request_body on;                #默认会开启
Context:    http, server, location
Indicates whether the client request body is mirrored. When enabled, the client request body will be read prior to creating mirror subrequests. In this case, unbuffered client request body proxying set by the proxy_request_buffering, fastcgi_request_buffering, scgi_request_buffering, and uwsgi_request_buffering directives will be disabled.
#同时官方给出明确指示,若请求体被镜像,那么在创建子请求之前会先读取请求体:
 
 
location / {
    mirror /mirror;
    mirror_request_body off;
    proxy_pass http://backend;
}
 
location = /mirror {
    internal;
    proxy_pass http://log_backend;
    proxy_pass_request_body off;
    proxy_set_header Content-Length "";
    proxy_set_header X-Original-URI $request_uri;
}
 
 
upstream backend {
    server backend.local:10000;
}
 
upstream test_backend {
    server test.local:20000;
}
 
server {
    server_name proxy.local;
    listen 8000;
 
    location / {
    mirror /mirror;
    proxy_pass http://backend;
    }
 
    location = /mirror {
    internal;
    proxy_pass http://test_backend$request_uri;
    }
}
 
 
#location = /mirror 中的 internal 指定此 location 只能被“内部的”请求调用,外部的调用请求会返回 ”Not found” (404)
 
 
镜像机制优势明显,但也并非没有缺憾。
 
当请求到达 Nginx 时,如果 Nginx 开启了流量镜像功能,它就会将请求复制一份,并根据 mirror location 中的配置来处理这份复制的请求。当前我们只是将复制的请求转发到镜像后端。
 
最关键部分是复制的镜像请求和原始请求是相关联的,若镜像请求没有处理完成,原始请求就会被阻塞。
 
总结一下,若镜像请求响应缓慢,原始请求就会被阻塞。
故此在开启流量镜像模式做为测试流量时,要认真监控Nginx性能指标,发现请求反馈异常要即时处理。
 
解决方案
如果你不确定镜像后端是否能够正确处理原始请求,你可以只复制一部分流量到镜像后端,例如 10%。
mirror 指令没有更多的配置项,它只会将所有的请求复制一份,并根据 mirror location 中的配置来处理请求,所以在 mirror 指令中下手是行不通的,我们只能修改 mirror location 中的配置。修改后的配置文件如下:
 
 
upstream backend {
    server backend.local:10000;
}
 
upstream test_backend {
    server test.local:20000;
}
 
split_clients $remote_addr $mirror_backend {
    50% test_backend;
    *   "";
}
 
server {
    server_name proxy.local;
    listen 8000;
 
    access_log /var/log/nginx/proxy.log;
    error_log /var/log/nginx/proxy.error.log info;
 
    location / {
        mirror /mirror;
        proxy_pass http://backend;
    }
 
    location = /mirror {
        internal;
        if ($mirror_backend = "") {
            return 400;
        }
 
        proxy_pass http://$mirror_backend$request_uri;
    }
 
}
 
在 mirror location 中,请求会被转发到 $mirror_backend 变量(proxy_pass http://$mirror_backend$request_uri)定义的后端。$mirror_backend 变量由 split_clients 配置块定义,split_clients 会将左边的变量 $remote_addr(requests remote address)经过 MurmurHash2 算法进行哈希,得出的值如果在前 50%(从 02147483500),那么 $mirror_backend 的值为 test_backend;如果不在前 50%,那么 $mirror_backend 的值为空字符 ""。
 
这样就实现了只复制部分流量到镜像后端,如果 $mirror_backend 变量的值为空字符串,就不复制流量;其他情况就会将流量到镜像后端。因为镜像请求的错误响应并不会影响原始请求,所以丢弃镜像请求并返回错误响应是很安全的。
 
这个方法的优点在于可以根据任何变量或变量组合来拆分镜像流量。如果想真正区分用户,那么 remote address 可能不适合作为拆分镜像流量的依据,因为用户可能会更换 IP。这时最好使用用户粘性密钥来拆分镜像流量,例如 API key。
 
比如,如果根据请求中的 apikey 来拆分镜像流量,只需要将 split_client 配置块中的 $remote_addr 改为 $arg_apikey:
 
split_clients $arg_apikey $mirror_backend {
    50% test_backend;
    *   "";
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Sicc1107

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值