微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Nginx流量拷贝ngx_http_mirror_module模块配置及分析

本文适合对Nginx比较感兴趣的同学阅读,需要具备一定的服务端编程知识。

一、背景
最近Nginx官网公布了Nginx1.13.4最新的ngx_http_mirror_module模块,利用mirror模块,业务可以将线上实时访问流量拷贝至其他环境,基于这些流量可以做版本发布前的预先验证,进行流量放大后的压测等等。本着兴趣笔者调研了其实现原理和使用方式,通过demo的形式展示给读者,希望能解决大家在使用过程中遇到的问题。

二、mirror模块配置
mirror模块配置分为两部分,源地址和镜像地址配置,配置位置可以为Nginx配置文件的http,server,location上下文,配置示例为:

# original配置
location / {
    mirror /mirror;
    mirror_request_body off;
    proxy_pass http://127.0.0.1:9502;
}
 
# mirror配置
location /mirror {
    internal;
    proxy_pass http://127.0.0.1:8081$request_uri;
    proxy_set_header X-Original-URI $request_uri;
}
1.original配置
location /指定了源uri为/

mirror /mirror指定镜像uri为/mirror

mirror_request_body off | on 指定是否镜像请求body部分,此选项与proxy_request_buffering、fastcgi_request_buffering、scgi_request_buffering和 uwsgi_request_buffering冲突,一旦开启mirror_request_body为on,则请求自动缓存;

proxy_pass 指定上游server的地址

2.mirror配置
internal 指定此location只能被“内部的”请求调用,外部的调用请求会返回”Not found” (404)

proxy_pass 指定上游server的地址

proxy_set_header 设置镜像流量的头部

按照上述配置,搭建了上图所示的验证环境,各个模块均部署在本机,由curl发起请求:

curl 127.0.0.1
original和mirror均为上游server PHP脚本,其中original返回响应response to client。 抓包结果如下图: 

分析抓包结果,整个请求流程为:

curl向Nginx 80端口发起GET / HTTP请求

Nginx将请求转发至upstream 9502端口的original PHP脚本,Nginx本地端口为51637

Nginx将请求镜像发至upstream 8081端口的mirror PHP脚本,Nginx本地端口为51638

original发送响应response to client至Nginx

Nginx将响应转发至curl,curl将响应展示到终端

mirror将响应发送至NginxNginx丢弃。

由此可见,在整个流程中,Nginx将请求转发送至original和mirror,然后等待响应,几乎不会对正常请求造成影响,整个处理过程是完全异步的。

三、mirror模块实现
static ngx_int_t
ngx_http_mirror_handler_internal(ngx_HTTP_Request_t *r)
{
    ngx_str_t                   *name;
    ngx_uint_t                   i;
    ngx_HTTP_Request_t          *sr;
    ngx_http_mirror_loc_conf_t  *mlcf;
 
    mlcf = ngx_http_get_module_loc_conf(r,ngx_http_mirror_module);
 
    name = mlcf->mirror->elts;
 
    for (i = 0; i < mlcf->mirror->nelts; i++) {
        if (ngx_http_subrequest(r,&name[i],&r->args,&sr,NULL,
                                NGX_HTTP_SUBREQUEST_BACKGROUND)
            != NGX_OK)
        {
            return NGX_HTTP_INTERNAL_SERVER_ERROR;
        }
 
        sr->header_only = 1;
        sr->method = r->method;
        sr->method_name = r->method_name;
    }
 
    return NGX_DECLINED;
}
Nginx有关mirror的代码位于文件src/http/modules/ngx_http_mirror_module.c文件,上述为文件中的ngx_http_mirror_handler_internal函数。在开启了mirror之后此函数会被执行,可见其内部主要通过ngx_http_subrequest发起http子请求来实现的。

通过代码可见,Nginx支持配置多个mirror uri,示例为:

location / {
    mirror /mirror;
    mirror /mirror2;
    mirror_request_body off;
    proxy_pass http://127.0.0.1:9502;
}
 
location /mirror {
    internal;
    proxy_pass http://127.0.0.1:8081$request_uri;
}
 
location /mirror2 {
    internal;
    proxy_pass http://127.0.0.1:8081$request_uri;
}
 

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐