灰度發布,簡單來說,就是根據各種條件,讓一部分用戶使用舊版本,另一部分用戶使用新版本。百度百科中解釋:灰度發布是指在黑與白之間,能夠平滑過渡的一種發布方式。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:
然后刷新瀏覽器:
返回生產服務器的結果。