如何利用 nginx 实现生产和灰度环境流量切换?

介绍


灰度发布(又名金丝雀发布)是指在黑与白之间,能够平滑过渡的一种发布方式。在其上可以进行A/B testing,即让一部分用户继续用产品特性A,一部分用户开始用产品特性B,如果用户对B没有什么反对意见,那么逐步扩大范围,把所有用户都迁移到B上面来。灰度发布可以保证整体系统的稳定,在初始灰度的时候就可以发现、调整问题,以保证其影响度。

根据 cookie 实现灰度配置


查询 cookie 键为 version 的值,如果该 cookie 值为 V1 则转发到 server_01,为 V2 则转发到 server_02,cookie 值都不匹配的情况下默认走 server_01 所对应的服务器。

使用 if 指令实现

upstream server_01 {
    server 192.168.1.100:8080 max_fails=1 fail_timeout=60;
}
upstream server_02 {
    server 192.168.1.101:8080 max_fails=1 fail_timeout=60;
}
server {
    listen 80;
    server_name www.server.com;
 
    #match cookie
    set $server "server_01";
    if ($http_cookie ~* "version=V1"){
        set $server server_01;
    }
    if ($http_cookie ~* "version=V2"){
        set $server server_02;
    }
    location / {
        proxy_pass http://$server;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        index index.html index.htm;
    }
}

使用 map 指令实现


upstream server_01 {
    server 192.168.1.100:8080 max_fails=1 fail_timeout=60;
}
upstream server_02 {
    server 192.168.1.101:8080 max_fails=1 fail_timeout=60;
}
map $COOKIE_version $server {
    ~*V1$ server_01;
    ~*V2$ server_02;
    default server_01;
}
server {
    listen 80;
    server_name www.server.com;
 
    location / {
        proxy_pass http://$server;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        index index.html index.htm;
    }
}

根据权重实现灰度配置


upstream server {
    server 192.168.1.100:8080 max_fails=1 fail_timeout=60 weight=5;
    server 192.168.1.101:8080 max_fails=1 fail_timeout=60 weight=1;
}
server {
    listen 80;
    server_name www.server.com;
 
    location / {
        proxy_pass http://server;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        index index.html index.htm;
    }
}

根据来路 IP 实现灰度配置


资源在不同服务器上


upstream server_01 {
    server 192.168.1.100:8080 max_fails=1 fail_timeout=60;
}
upstream server_02 {
    server 192.168.1.101:8080 max_fails=1 fail_timeout=60;
}
server {
    listen 80;
    server_name www.server.com;
 
    set $server "server_01";
    if ($remote_addr ~ "211.118.119.11"){
        set $server server_02;
    }
    location / {
        proxy_pass http://$server;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        index index.html index.htm;
    }
}

资源在同一服务器上


server {
    listen 80;
    server_name www.server.com;
 
    set $rootdir "/var/www/html";
    if ($remote_addr ~ "211.118.119.11"){
        set $rootdir "/var/www/test";
    }
    location / {
        root $rootdir;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        index index.html index.htm;
    }
}

Nginx+Lua 实现灰度配置


如果来源 IP 地址是 ipList.conf 中的地址,那么就定位到 test_env,如果来源 IP 地址不在 ipList.conf 中(即有效用户 IP),那么就定位到 product_env。

local ip_config = ngx.shared.config;
ClienIP=ngx.req.get_headers()["X-Real-IP"]
if ClientIP == nil then
    ClientIP = ngx.req.get_headers()["x_forworded_for"]
end
if ClientIP == nil then
    ClientIP = ngx.var.remote_addr
end
for line in io.lines("/usr/local/nginx/conf/lua/ipList.conf") do
    if not ip_config:get(line) then
        ip_config:set(line, "0")
    end
end
if ip_config:get(ClientIP) == "0" then
    ngx.exec("@test_env")
else
    ngx.exec("@product_env")
end

ipList.conf 内容格式

lua_code_cache on;
lua_shared_dict config 1m;
 
upstream MyServer {
    server 192.168.1.199:8099 max_fails=3 fail_timeout=30s;
    server 192.168.1.200:8099 max_fails=3 fail_timeout=30s;
    ip_hash;
}
server {
    listen 80;
    server_name jokerzhang.cn;
    access_log off;
    #access_log logs/jokerzhang.log;
 
    location / {
        access_by_lua_file /usr/local/nginx/conf/lua/ip_gray.lua;
    }
    location @test_env {
        proxy_pass http://192.168.1.199:8099;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
    location @product_env {
        proxy_pass http://MyServer;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

版权声明:本文为作者原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

原创文章,作者:老C,如若转载,请注明出处:https://www.code404.icu/1295.html

发表评论

登录后才能评论