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;
}
}