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將響應發送至nginx,nginx丟棄。

由此可見,在整個流程中,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;
}
 

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