你好呀,我是趙興晨,文科程序員。
下面的內容可以說是干貨滿滿建議先收藏再慢慢細品。
今天,我想與大家深入探討一個我們日常工作中不可或缺的話題——灰度環境。你是否在工作中使用過灰度環境?如果是,你的使用體驗如何?
俗話說得好:“不想成為架構師的Java程序員,不是一個好的SRE。(Site Reliability Engineer,即網站可靠性工程師)”這句話看似是一句玩笑話,但是它道出了一個程序員不斷追求技術深度與廣度的重要性。
在日常工作中,我們不僅要精通Java,還需要掌握運維和前端技術等多方面技能,而灰度環境的構建與管理正是其中的關鍵一環。
那么什么是灰度發布呢?
灰度發布是指在黑與白之間,能夠平滑過渡的一種發布方式。AB Test 就是一種灰度發布。 讓一部分用戶繼續使用環境A, 一部分用戶開始使用環境B,如果用戶對環境B沒有什么反對意見,那么逐步擴大范圍,把所有用戶都遷移到環境B上面來。灰度發布可以保證整體系統的穩定,在初始灰度的時候就可以發現問題并及時調整,以保證其小范圍的影響度。
常見的灰度發布的方式
Nginx + Lua 實現灰度
這個說來話長,涉及到的內容太多,我在做技術選型的時候直接給這個方案pass掉了,這里就不做過多贅述。
基于 cookie 實現灰度
根據查詢cookie鍵為version的值,如果cookie值為gray,則轉發到linux_gray(灰度環境),cookie的值都不匹配的情況下,默認走linux_prod(生產環境)。
舉個例子:
兩個后端應用服務器分別定義為
# 灰度環境
linux_gray 10.0.0.60:10001# 生產環境
linux_prod 10.0.0.61:10001
使用map指令實現
在Nginx里面配置一個映射,$COOKIE_version 可以解析出Cookie 里面的 version 字段, $group 是一個變量, {} 里面是映射規則。
如果一個 version為gray 的用戶來訪問,$group 就等于linux_gray。在 server 里面使用就會代理到http://linux_gray 上。
否則,$group 就等于 linux_prod。在 server 里面使用就會代理到 http://linux_prod 上。Cookie 值都不匹配的情況下默認走 linux_prod 所對應的服務器。
以下👇是基于cokkie實現灰度的Nginx配置參考。
# 灰度環境
upstream linux_gray {server 10.0.0.60:10001;
}# 生產環境
upstream linux_prod {server 10.0.0.61:10001;
}# 后端服務
map $COOKIE_version $group {~*gray$ linux_gray;default linux_prod;
}# 前端靜態資源
map $COOKIE_version $grouppath {~*gray$ /web/staticGray/;default /web/staticProd/;
}server {listen 80;server_name linuxtest.com;access_log logs/linux.log main;# 后端服務location /server/test { # 進入灰度環境增加響應標識if ( $COOKIE_version ~* "gray$" ){add_header version gray always;}# rewrite解決 /test丟失問題rewrite ^/server/(.*) /$1 break;proxy_pass http://$group;}# 靜態資源location /serverweb {if ( $COOKIE_version ~* "gray$" ){add_header version gray always;}alias $grouppath;try_files $uri $uri/ /index.html;index index.html;}
}
根據用戶訪問的IP 實現灰度
nginx 對用戶的IP進行分流,將符合分流規則的用戶IP指到linux_gray(灰度環境),其余的指到 linux_prod(生產環境)
舉個例子:
兩個后端應用服務器分別定義為
# 灰度環境
linux_gray 10.0.0.60:10001# 生產環境
linux_prod 10.0.0.61:10001
跟cookie的差不多 也是使用map指令實現的,但需要獲取用戶的真實IP地址。
# 灰度環境
upstream linux_gray {server 10.0.0.60:10001;
}# 生產環境
upstream linux_prod {server 10.0.0.61:10001;
}# 后端服務
map $remote_addr $group {# 只允許用戶ip為10.0.0.75的用戶訪問灰度環境# 也可以設置成ip段 ~*^10\.0\.0\.(.*?)$~10.0.0.75 linux_gray;default linux_prod;
}# 前端靜態資源
map $remote_addr $grouppath {~10.0.0.75 /web/staticGray/;default /web/staticProd/;
}server {listen 80;server_name linuxtest.com;access_log logs/linux.log main;# 獲取用戶真實IPset_real_ip_from 127.0.0.1; # 真實服務器上一級代理的IP地址或者IP段,可以寫多行real_ip_header X-Forwarded-For; # 從哪個header頭檢索出要的IP地址real_ip_recursive on; #遞歸排除IP地址,ip串從右到左開始排除set_real_ip_from里面出現的IP,如果出現了未出現這些ip段的IP,那么這個IP將被認為是用戶的IP# 后端服務location /server/test { # 進入灰度環境增加響應標識if ( $remote_addr ~* "10.0.0.75" ){add_header version gray always;}# rewrite解決 /test丟失問題rewrite ^/server/(.*) /$1 break;proxy_pass http://$group;}# 靜態資源location /serverweb {if ( $remote_addr ~* "10.0.0.75" ){add_header version gray always;}alias $grouppath;try_files $uri $uri/ /index.html;index index.html;}# 測試用戶訪問獲取用戶IPlocation /iptest {return 200 $remote_addr;}
}
上面這三種方案就是當時我做技術選型能夠搜集到的方案, 基于cookie實現灰度會出現好多問題,不太符合現有系統:
1、獲取cookie的時機問題,如默認用戶第一次進入到系統,需要判斷該用戶是否是灰度用戶,如果是灰度用戶下次請求會攜帶cookie,這樣前端靜態資源第一次進入到的是生產環境,需要重新刷新才能進入到灰度環境,對用戶不太友好。
2、如果灰度環境出現問題,需要回滾,回滾后無法保證用戶實時切換回生產環境,因為只有用戶登錄的時候才會確定該用戶是否是灰度用戶,如果灰度用戶在使用中,沒有重新登錄,會一直在灰度環境,除非強制將用戶踢下線,提示用戶重新登錄,這樣對用戶體驗也不友好。
所以基于以上的兩個問題,最終決定選用基于用戶IP來實現灰度發布。
基于用戶IP實現灰度的核心所在是獲取用戶真實IP,并根據用戶的真實IP特征來決定進入灰度的規則,IP規則可以是IP段。
以上就是我個人的一些思考,如果有不正確的地方,歡迎大家在文章底部留言指正。
如果你是第一次接觸Centos7、Nginx建議看一下我之前的文章:
掃描下方👇二維碼關注我,可查看相關知識點干貨!
最后,我想說的是:點贊和分享不僅僅是一種美德,更是對未來美好生活的投資。愿每一個點在看的朋友,未來都能收獲滿滿的幸福和成功!
你好,我是趙興晨,一名文科程序員。我期待在文章下方看到你的留言,讓我們一起交流,共同進步。