企業實戰|Nginx多策略流量分發


1、場景描述

在實際生產環境中,流量分發有很多情況,下面主要講講以下兩種流量分發場景:

  1. 新版本上線,為了保證新版本穩定性,需要用線上的流量的引入,對新版本進行真實流量測試。如果新版本上線有問題,為降低影響范圍,我們對流量的引入應該為從小到大的策略。

  2. 現如今是移動端的時代,而移動端和pc端的設備的不同,需要對移動端和pc的流量進行不同的處理,同時可以針對兩種設備的不同需求可以單獨升級,可控性強,且架構靈活。

2、nginx策略配置

針對以上兩種場景,nginx做為強大的web服務器,通過簡單的配置來就可以滿足我們的需求,下面我們就開始實戰:

nginx version: nginx/1.16.1
os version: centos 7

完成以上需求,主要依賴於nginx的兩個模塊:

  1. ngx_http_split_clients_module 文檔參考地址: http://nginx.org/en/docs/http/ngx_http_split_clients_module.html

  2. ngx_http_map_module 文檔參考地址:http://nginx.org/en/docs/http/ngx_http_map_module.html

3、流量按比例分配[ngx_http_split_clients_module]

按比例分配流量,通過ngx_http_split_clients_module模塊實現,該模塊可通過客戶端的某些屬性對客戶端通過hash算法按比例分配,這些屬性包括客戶端ip等,通過hash函數,將不同客戶端ip進行比例分配,從而可以將部分流量引入新版本服務中,下面看一下具體配置:

user nobody;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;

events {
worker_connections 1024;
}

http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
user nobody;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;

events {
worker_connections 1024;
}

http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';

access_log /var/log/nginx/access.log main;

include /etc/nginx/mime.types;
default_type application/octet-stream;

# 根據內置變量變量${remote_addr}進行1:1分發,並將v1和v2的值賦予$version變量
split_clients "${remote_addr}AAA" $version {
50% v1;
* v2;
}

# v1版本服務
server {
listen 8081;
location / {
return 200 "v1\n";
}
}
# v2版本服務
server {
listen 8082;
location / {
return 200 "v2\n";
}
}

server {
listen 80;
location / {
proxy_pass http://127.0.0.1/$version;
}
# v2版本轉發
location /v2 {
proxy_pass http://127.0.0.1:8082/;
}
# v1版本轉發
location /v1 {
proxy_pass http://127.0.0.1:8081/;
}
}
}

在配置中,我們利用split_clients指令對$remote_addr變量進行hash運算,並按1:1比例隨機地將$version的值賦予v1和v2,*表示剩余的比例,即1-50%,這樣就可以通過$version的值進行流量分配,具體可看nginx配置,已有注釋。可以看到在版本轉發時,在proxy_pass轉發路徑最后加了/,是為了把版本路徑(v1|v2)去掉,然后再進行轉發,可以保持原有的請求uri路徑不變,此處算是一個小技巧。

實際效果:

4、移動端和pc端流量分配[ngx_http_map_module]

ngx_http_map_module模塊可通過客戶端屬性按一定規則匹配映射為新的變量,我們可以對客戶端的ua進行正則匹配來區分流量,從而進行流量分發,下面是nginx配置文件示例:

user nobody;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;

events {
worker_connections 1024;
}

http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';

access_log /var/log/nginx/access.log main;

include /etc/nginx/mime.types;
default_type application/octet-stream;


map "${http_user_agent}" $uatype {
default nomobile;
"~*mobile" mobile;
}

# pc端服務
server {
listen 8082;
location / {
return 200 "nomobile\n";
}
}

# 移動端服務
server {
listen 8081;
location / {
return 200 "mobile\n";
}
}

server {
listen 80;
location / {
proxy_pass http://127.0.0.1/$uatype;
}
# pc端版本轉發
location /nomobile {
proxy_pass http://127.0.0.1:8082/;
}
# 移動端版本轉發
location /mobile {
proxy_pass http://127.0.0.1:8081/;
}
}
}

在nginx配置中,我們可以看到使用map指令,對客戶端的ua進行正則匹配,一旦匹配成功,$uatype將被分配為mobile,並根據此變量的值進行轉發,剩下未匹配的由default 指定,此時$uatype為nomobile,從而轉發到pc端服務,同時在轉發到后端時,同樣在proxy_pass后加/,也是為了去掉nomobile和mobile前綴。在使用map的正則匹配時,代表區分大小寫的匹配,*則為不區分大小寫。

實際效果:

5、總結

以上只是列舉典型的流量分發方式,我們可以根據$http_name或者$arg_name來定制化需求,$http_name獲取自定義頭部,$arg_name獲取自定義uri參數,這就給予我們更多的可能,比如我們可以再用戶登錄后,添加自定義頭部,使用自定義頭部,map指令進行流量拆分,更多的用途需要我們自行發揮想象進行探索。

 


☆ END ☆


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM