Openresty+Lua+Redis灰度發布


灰度發布,簡單來說,就是根據各種條件,讓一部分用戶使用舊版本,另一部分用戶使用新版本。百度百科中解釋:灰度發布是指在黑與白之間,能夠平滑過渡的一種發布方式。AB test就是一種灰度發布方式,讓一部分用戶繼續用A,一部分用戶開始用B,如果用戶對B沒有什么反對意見,那么逐步擴大范圍,把所有用戶都遷移到B上面 來。灰度發布可以保證整體系統的穩定,在初始灰度的時候就可以發現、調整問題,以保證其影響度。上述描述的灰度方案A和B需要等量的服務器,這里我們所做的灰度發布稍作改變:用1-2台機器作為B,B測試成功再部署A。用於WEB系統新代碼的測試發布,讓一部分(IP)用戶訪問新版本,一部分用戶仍然訪問正常版本,原理如圖:

執行過程:
1、當用戶請求到達前端web(代理)服務器Openresty,內嵌的lua模塊解析Nginx配置文件中的lua腳本代碼;
2、Lua獲取客戶端IP地址,去查詢Redis中是否有該鍵值,如果有返回值執行@clien2,否則執行@client1。
3、Location @client2把請求轉發給預發布服務器,location @client1把請求轉發給生產服務器,服務器返回結果,整個過程完成。

Openresty部分配置如下:

upstream client1 { 
        server 127.0.0.1:8080;  #模擬生產服務器
    }
upstream client2 {
        server 127.0.0.1:8090;  #模擬預發布服務器
    }

server {
        listen       80;
        server_name  localhost;
        
        location ^~ /test {
            content_by_lua_file /app/ngx_openresty/nginx/conf/huidu.lua
        }
        
        location @client1{
                proxy_pass http://client1;
        }
        location @client2{
                proxy_pass http://client2;
        }
     }

Lua腳本內容如下:

local redis = require "resty.redis" 
local cache = redis.new() 
cache:set_timeout(60000)

local ok, err = cache.connect(cache, '127.0.0.1', 6379) 
if not ok then 
    ngx.say("failed to connect:", err) 
    return 
end 

local red, err = cache:auth("foobared")
if not red then
    ngx.say("failed to authenticate: ", err)
    return
end

local local_ip = ngx.req.get_headers()["X-Real-IP"]
if local_ip == nil then
    local_ip = ngx.req.get_headers()["x_forwarded_for"]
end

if local_ip == nil then
    local_ip = ngx.var.remote_addr
end
--ngx.say("local_ip is : ", local_ip)

local intercept = cache:get(local_ip) 


if intercept == local_ip then
    ngx.exec("@client2")
    return
end

ngx.exec("@client1")

local ok, err = cache:close() 
 
if not ok then 
    ngx.say("failed to close:", err) 
    return 
end

驗證:
url:http://192.168.116.145/test/n.jpg (模擬生產環境)
客戶端IP:192.168.116.1(模擬公司辦公網IP)

1、訪問http://192.168.116.145/test/n.jpg
返回的結果是生產服務器的。

在Redis存入客戶端IP:

繼續訪問:
請求到的是預發布服務器返回的結果。

在Redis中刪除客戶端IP:

然后刷新瀏覽器:
返回生產服務器的結果。


免責聲明!

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



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