Nginx http_mirror_module 实现流量复制

http_mirror_module功能和特性


mirror模块可以帮助我们创建一份镜像流量,比如在生产环境下处理一些请求,这些请求可能要同步的copy一份到我的测试环境当中或者开发环境当中做处理,mirror模块就可以实现。

每当我们的请求到了nginx之后,可以生成子请求。这个子请求可以通过反向代理去访问我们其他的环境,比如我们的测试环境。而对测试环境和其他环境返回的内容我们是不做处理的,因为只做镜像的。

利用mirror模块,业务可以将线上实时访问流量拷贝至其他环境,基于这些流量可以做版本发布前的预先验证,进行流量放大后的压测等等。(复制线上真实流量,在不影响真实业务前提下,利用复制流量来做故障分析、性能定位、迁移评估等功能。)

  • nginx 1.13.4及后续版本内置ngx_http_mirror_module模块,提供流量镜像(复制)的功能。
  • 支持流量放大,做法为:配置多份相同镜像。
  • 相比tcp-copy的优势:无需录制流量,实时可用;配置相当简单。
  • 源站请求,直接原路返回;正常配置下,mirror请求不影响源站请求及响应,源站nginx-server将流量复制到mirror站后,两者不再有任何交集。

http_mirror_module语法


Syntax: mirror uri | off;  --url是指需要将同步复制的请求访问到另外一个url上面去,即指向反向代理
Default: mirror off;  --默认是关闭的
Context: http, server, location

Syntax: mirror_request_body on | off;  --是否需要将请求中的body转发到上游服务当中,默认是要复制http body的,指明off就不需要复制body了
Default: mirror_request_body on;
Context: http, server, location

 

配置流量复制


192.168.179.99流量镜像复制到上游服务192.168.179.100,配置如下:

192.168.179.99源站配置配置如下
[root@www ~]# echo "mirror.txt" > /usr/local/nginx/html/mirror.txt

server {
        listen       80;
        server_name  localhost;

      location / {
        mirror /mirror;
        mirror_request_body off;
      }

      location =/mirror{
         proxy_pass http://192.168.179.100$request_uri;  
         #原始uri不会镜像,可以通过#$request_uri变量取得原始请求的uri
         proxy_set_header Host $host;
         proxy_set_header X-Real-IP $remote_addr;

      }
}


192.168.179.100镜像站配置
server{
      listen  80;
      server_name localhost;
      charset utf-8;
      error_page 404 =200 /404.html;
      location /{
      return 200 'mirror respone';
     }
}


客户端192.168.179.102去请求192.168.179.99资源
[root@localhost ~]# curl 192.168.179.99/mirror.txt
mirror.txt

-----------------------------------------------------------------------------------------
192.168.179.99日志如下:
192.168.179.102 - - [29/Apr/2020:11:30:09 +0800] "GET /mirror.txt HTTP/1.1" 200 11 "-" "curl/7.29.0" "-"       --通过日志可以看到99收到了该请求

192.168.179.100日志如下:
192.168.179.99 - - [29/Apr/2020:11:30:09 +0800] "GET /mirror.txt HTTP/1.0" 200 14 "-" "curl/7.29.0" "192.168.179.102"   --上游服务也收到该请求,可以看到时间也是一样
可以看到上游服务和代理服务都拿到到了客户端相同的请求这样实现了流量的拷贝

 

 流量放大配置方法


配置多分mirror 

server {
        listen       80;
        server_name  web1.www.com;
        # 源站配置
        location / {
                access_log  /data/nginx/1.14.1/logs/web1/access.log  accesslog;
                mirror /mirror;
                # 多加一份mirror,流量放大一倍
                mirror /mirror;
                mirror_request_body on;# Indicates whether the client request body is mirrored. default value is on.
                proxy_pass http://web1.upstream.name;
        }
        # 镜像站点配置
        location /mirror {
                internal; 
#internal 指定此location只能被“内部的”请求调用,外部的调用请求会返回”Not found” (404)
#跳转到下面的内部server
                proxy_pass http://mirror.web1.upstream.name$request_uri;
                proxy_pass_request_body on; 
# Indicates whether the original request body is passed to the proxied server. default #value is on
 
               proxy_set_header X-Original-URI $request_uri; # reset uri
        }
}

 

mirror日志


镜像配置不正确,导致复制操作没正常执行,此时nginx可能缺少错误日志,严重影响调试,所以非常建议配置镜像日志。mirror中不支持配置access_log,解决方法:mirror-location跳转到server,在server中配置accesslog。 

server {
        listen       80;
        server_name  web1.www.com;
 
        # 源站配置
        location / {
                access_log  /data/nginx/1.14.1/logs/web1/access.log  accesslog;
                mirror /mirror;
                mirror_request_body off;# Indicates whether the client request body is mirrored. default value is on.
                proxy_pass http://web1.upstream.name;
        }
 
        # 镜像站点配置
        location /mirror {
                internal; # 内部配置
                # 跳转到下面的内部server
                proxy_pass http://127.0.0.1:10901$request_uri;
                proxy_pass_request_body off; # Indicates whether the original request body is passed to the proxied server. default value is on
                # Content-Length必须配置在mirror中否则无效
                proxy_set_header Content-Length ""; 
# mirror_request_body/proxy_pass_request_body都设置为off,则Conten-length需要设置为"",否则有坑
                proxy_set_header X-Original-URI $request_uri; # 使用真实的url重置url
        }
}
 
server {
    # server没法设置为内部
    listen 127.0.0.1:10901;
    location / {
        # 判断放在server,使得post请求日志可以记录
        if ($request_method != GET) {
            return 403;
        }
        access_log /data/nginx/1.14.1/logs/web1/access.log  accesslog;
        proxy_pass http://mirror.web1.upstream.name;
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章