《利用ngx_http_mirror_module實(shí)現(xiàn)流量鏡像》要點(diǎn):
本文介紹了利用ngx_http_mirror_module實(shí)現(xiàn)流量鏡像,希望對您有用。如果有疑問,可以聯(lián)系我們。
背景
最近 Nginx 官網(wǎng)發(fā)布了 Nginx 1.13.4,Nginx 1.13.4 中新增了一個(gè) ngx_http_mirror_module
模塊.通過 mirror 模塊,可實(shí)現(xiàn)對原始請求創(chuàng)建后臺鏡像,鏡像子請求的輸出會被忽略.
利用這一功能我們就可以將線上實(shí)時(shí)訪問流量拷貝至其它環(huán)境,基于這些流量可以做版本發(fā)布前的預(yù)先驗(yàn)證或者進(jìn)行流量放大后的壓測等等.
在這之前與這一功能類似的軟件有:TCPCopy等,Nginx 自身支持后使用起來就更加方便了.下面我們來看看具體的如何配置:
mirror 模塊在 Nginx 1.13.4中默認(rèn)是啟用的,如果要禁用這個(gè)功能可在編譯時(shí)加上 --without-http_mirror_module
參數(shù).
$ apt-get install libreadline-dev libncurses5-dev libpcre3-dev libssl-dev perl make build-essential $ wget http://nginx.org/download/nginx-1.13.4.tar.gz $ tar xzvf nginx-1.13.4.tar.gz $ cd nginx-1.13.4/ $ ./configure $ make && make install
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; }
在這個(gè)示例中我們配置了兩組后臺服務(wù)器,http://127.0.0.1:9502
指向生產(chǎn)服務(wù)器, http://127.0.0.1:8081
指向測試服務(wù)器.用戶訪問生產(chǎn)服務(wù)器的同時(shí),請求會被 Nginx 復(fù)制發(fā)送給測試服務(wù)器,需要注意的一點(diǎn)是 mirror 不會輸出 http 返回內(nèi)容.
指定了源 uri 為 /
指定鏡像 uri 為 /mirror
指定是否鏡像請求 Body 部分,此選項(xiàng)與proxy_request_buffering
、fastcgi_request_buffering
、scgi_request_buffering
和 uwsgi_request_buffering
沖突,一旦開啟mirror_request_body
為 on,則請求自動(dòng)緩存.
指定上游 Server 的地址.
指定此 location 只能被內(nèi)部的請求調(diào)用,外部的調(diào)用請求會返回 Not found (404).
指定上游 Server 的地址.
設(shè)置鏡像流量的頭部.
按照上述配置,搭建了上圖所示的驗(yàn)證環(huán)境,各個(gè)模塊均部署在本機(jī),由curl發(fā)起請求:
$ curl 127.0.0.1
original 和 mirror 均為上游 Server PHP 腳本,其中 original 返回響應(yīng) response to client. 抓包結(jié)果如下圖:
分析抓包結(jié)果,整個(gè)請求流程為:
由此可見,在整個(gè)流程中 Nginx 將請求轉(zhuǎn)發(fā)送至 original 和 mirror,然后等待響應(yīng).幾乎不會對正常請求造成影響,整個(gè)處理過程是完全異步的.
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 有關(guān) mirror 的代碼位于文件 src/http/modules/ngx_http_mirror_module.c
文件,上述為文件中的 ngx_http_mirror_handler_internal
函數(shù).在開啟了 mirror 之后此函數(shù)會被執(zhí)行,可見其內(nèi)部主要通過 ngx_http_subrequest
發(fā)起 http 子請求來實(shí)現(xiàn)的.
通過代碼可見,Nginx 支持配置多個(gè) 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; }
http://www.google.com
http://blog.csdn.net/xhjcehust/article/details/77093074
http://nginx.org/en/docs/http/ngx_http_mirror_module.html
文章來自微信公眾號:運(yùn)維之美
轉(zhuǎn)載請注明本頁網(wǎng)址:
http://www.fzlkiss.com/jiaocheng/1969.html