作爲技術人員,大家可能聽說過“滾動發佈”和“藍綠髮布”等術語,但是很多人並不清楚這些術語背後的原理。本文試圖總結當前主流的發佈策略,每個的優劣,適用性,讓開發人員特別是架構師對現代發佈技術有一個更爲清晰全面的認識,讓大家能夠根據自己的企業上下文,對發佈策略做出正確的選型和實踐。
一、單服務器組發佈
先解釋下單服務器組的概念,早先我們機器資源比較緊張,不像現在雲計算和虛擬化(包括容器技術)這麼發達,所以應用機器基本是預先靜態分配好的(一般由運維負責分配),原來應用 A 住在這 n 臺機器上,那麼下次升級發佈的應用 A 也住在這 n 臺機器上,所以稱爲單服務器組發佈方式。
1.1 蠻力發佈
如下圖所示,這種發佈方式比較簡單粗暴,有點像我們傳統的軟件升級方式,主要靠手工完成,先將老版本 V1 全部下掉,再將新版本發到機器上去。這種方式會引入服務中斷(停機),在開發測試環境是可行的,但對於生產環境發佈,其會直接影響用戶的使用體驗,這種方式一般是不建議的。
發佈前
發佈後
優勢和適用場合
優勢:
-
簡單成本低
不足:
-
服務中斷用戶受影響,出了問題回退也慢
適用場合:
-
開發測試環境
-
非關鍵應用(用戶影響面小)
-
初創公司什麼都缺,找夜深人靜用戶訪問量小的時間幹
流量模式
蠻力發佈會引入服務中斷時間,圖片來自附錄 6.1
1.2 金絲雀發佈(單服務器組)
在蠻力發佈基礎上的一種簡單改進發布方式,目前仍然是不少成長型技術組織的主流發佈方式。單服務器組下的金絲雀發佈的簡化步驟如下圖所示:
發佈前
先發一臺金絲雀
全部發完
實踐要點
-
金絲雀發佈一般先發 1 臺,或者一個小比例,例如 2% 的服務器,主要做流量驗證用,也稱爲金絲雀 (Canary) 測試(國內常稱灰度測試)。以前曠工開礦下礦洞前,先會放一隻金絲雀進去探是否有有毒氣體,看金絲雀能否活下來,金絲雀發佈由此得名。簡單的金絲雀測試一般通過手工測試驗證,複雜的金絲雀測試需要比較完善的監控基礎設施配合,通過監控指標反饋,觀察金絲雀的健康狀況,作爲後續發佈或回退的依據。
-
如果金絲測試通過,則把剩餘的 V1 版本全部升級爲 V2 版本。如果金絲雀測試失敗,則直接回退金絲雀,發佈失敗。
優勢和適用場合
優勢:
-
用戶體驗影響小,金絲雀發佈過程出現問題隻影響少量用戶
不足:
-
發佈自動化程度不夠,發佈期間可引發服務中斷
適用場合:
-
對新版本功能或性能缺乏足夠信心
-
用戶體驗要求較高的網站業務場景
-
缺乏足夠的自動化發佈工具研發能力
流量模式
少量金絲雀先接受流量,再全量發佈,圖片來自附錄 6.1
1.3 滾動式發佈(單服務器組)
在金絲雀發佈基礎上的進一步優化改進,是一種自動化程度較高的發佈方式,用戶體驗比較平滑,是目前成熟型技術組織所採用的主流發佈方式。單服務器組下的滾動發佈的簡化步驟如下圖所示:
發佈前
發佈中,先發一臺金絲雀
發佈中,再發若干臺
直到全部發完
實踐要點
-
滾動式發佈一般先發 1 臺,或者一個小比例,如 2% 服務器,主要做流量驗證用,類似金絲雀 (Canary) 測試。
-
滾動式發佈需要比較複雜的發佈工具和智能 LB,支持平滑的版本替換和流量拉入拉出。
-
每次發佈時,先將老版本 V1 流量從 LB 上摘除,然後清除老版本,發新版本 V2,再將 LB 流量接入新版本。這樣可以儘量保證用戶體驗不受影響。
-
一次滾動式發佈一般由若干個發佈批次組成,每批的數量一般是可以配置的(可以通過發佈模板定義)。例如第一批 1 臺(金絲雀),第二批 10%,第三批 50%,第四批 100%。每個批次之間留觀察間隔,通過手工驗證或監控反饋確保沒有問題再發下一批次,所以總體上滾動式發佈過程是比較緩慢的 (其中金絲雀的時間一般會比後續批次更長,比如金絲雀 10 分鐘,後續間隔 2 分鐘)。
-
回退是發佈的逆過程,將新版本流量從 LB 上摘除,清除新版本,發老版本,再將 LB 流量接入老版本。和發佈過程一樣,回退過程一般也比較慢的。
-
滾動式發佈國外術語通常叫 Rolling Update Deployment。
優勢和適用場合
優勢:
-
用戶體驗影響小,體驗較平滑
不足:
-
發佈和回退時間比較緩慢
-
發佈工具比較複雜,LB 需要平滑的流量摘除和拉入能力
適用場合:
-
用戶體驗不能中斷的網站業務場景
-
有一定的複雜發佈工具研發能力;
流量模式
滾動式發佈,流量平滑過渡,圖片來自附錄 6.1
二、雙服務器組發佈
隨着雲計算和虛擬化技術的成熟,特別是容器等輕量級虛擬化技術的引入,計算資源受限和申請緩慢問題已經逐步解決,可以做到彈性按需分配。爲一次發佈分配兩組服務器,一組運行現有的 V1 老版本,一組運行待上線的 V2 新版本,再通過 LB 切換流量方式完成發佈,這就是所謂的雙服務器組發佈方式。
2.1 藍綠髮布(雙服務器組)
藍綠髮布僅適用於雙服務器組發佈,可以認爲是對蠻力發佈的一種簡單優化發佈方式。簡化過程如下圖所示:
實踐要點
-
V1 版本稱爲藍組,V2 版本稱爲綠組,發佈時通過 LB 一次性將流量從藍組直接切換到綠組,不經過金絲雀和滾動發佈,藍綠髮布由此得名;
-
出現問題回退也很直接,通過 LB 直接將流量切回藍組。
-
發佈初步成功後,藍組機器一般不直接回收,而是留一個待觀察期,視具體情況觀察期的時間可長可短,觀察期過後確認發佈無問題,則可以回收藍組機器。
優勢和適用場合
優勢:
-
升級切換和回退速度非常快
不足:
-
切換是全量的,如果 V2 版本有問題,則對用戶體驗有直接影響;
-
需要兩倍機器資源;
適用場合:
-
對用戶體驗有一定容忍度的場景
-
機器資源有富餘或者可以按需分配(AWS 雲,或自建容器雲)
-
暫不具備複雜滾動發佈工具研發能力;
流量模式
藍綠髮布一次完成流程切換,圖片來自附錄 7.1
2.2 金絲雀發佈(雙服務器組)
對藍綠部署的一種簡單優化,發佈時先從綠組拉入 1 臺金絲雀,待金絲雀驗證通過再發全量。對比藍綠髮布,該發佈方式的優勢是有一個生產流量的金絲雀驗證過程,可以減輕 V2 可能有問題的風險和影響面。簡化發佈過程如下圖所示:
2.3 滾動式發佈(雙服務器組)
滾動式發佈是對上面的藍綠和金絲雀發佈的進一步優化,按批次增量滾動發佈,提供更平滑的用戶體驗。
實踐要點
-
發佈前先申請一批新服務器,數量一般和 V1 版本相同,將 V2 版本應用發佈到新服務器上。例如如果在 AWS 雲上,則可以直接調用 API 申請一批新 VM,如果用容器雲 Kubernetes,則可以直接啓動一批新容器(使用 V2 版本容器鏡像)。
-
一般會先通過 LB 拉入 1 臺 V2 版本的機器,這臺機器也相當於金絲雀,用於流量驗證。
-
逐步按批次完成發佈,每批只需要通過 LB 拉入 V2 版本,再拉出對應數量的 V1 版本。批次之間留有觀察間隔,通過手工或監控反饋確保沒有問題再繼續發佈。
-
發佈有問題回退很快,直接通過 LB 將流量切回 V1 即可。
-
完成發佈後,一般 V1 版本要保留觀察以備萬一,比如留 1 天,1 天后沒有問題則回收 V1 機器資源。
優勢和適用場合
優勢:
-
用戶體驗影響小;
-
升級切換和回退(rollback)速度比單服務器組滾動發佈要快,LB 切流量即可;
不足:
-
需要兩倍機器資源;
-
發佈工具比較複雜,LB 需要流量切換能力
適用場合:
-
用戶體驗不能中斷的網站業務場景
-
機器資源有富餘或者可以按需分配(AWS 雲,或自建容器雲)
-
有一定的發佈工具研發能力;
流量模式
滾動式發佈,流量平滑過渡,圖片來自附錄 6.1
三、其它發佈方式
上述都是偏傳統的發佈方式,能覆蓋大部分應用發佈場景。針對一些關鍵新功能的上線發佈,或者一些特定的場景,還有一些特殊的發佈方式。
3.1 功能開關發佈
利用代碼中的功能開關(Feature Flag/Toggle/Switch)來控制發佈邏輯,一般不需要複雜的發佈工具和智能 LB 配合,是一種相對比較低成本和簡單的發佈方式。這種方式也是支持現代 DevOps 理念,研發人員可以靈活定製和自助完成的發佈方式。功能開關的原理如下圖所示:
功能開關發佈,圖片來自附錄 6.2
實踐要點
-
功能開關發佈需要一個配置中心或者開關中心這樣的服務支持,例如攜程的 Apollo 配置中心附錄 6.3,或者開源的 FF4J附錄 6.4,這些都支持開關發佈,業界還有專門的功能開關 SaaS 服務,例如 LaunchDarkly附錄 6.5。通過配置中心,運維或研發人員可以在運行期動態配置功能開關的值。當然,功能開關發佈只是配置中心的一種使用場景,配置中心還能支持其它很多動態配置場景。
-
功能開關服務一般提供客戶端 SDK,方便開發人員集成。在運行期,客戶端 SDK 會同步最新的開關值,技術實現有推方式 (push),也有拉方式 (pull),或者推拉結合方式。
-
新功能(V2 new feature)和老功能(V1 old feature)住在同一套代碼中,新功能隱藏在開關後面,如果開關沒有打開,則走老代碼邏輯,如果開關打開,則走新代碼邏輯。技術實現上可以理解爲一個簡單的 if/else 邏輯。
-
應用上線後,開關先不打開,然後運維或研發人員通過開關中心打開新功能,經過流量驗證新功能沒有問題,則發佈完成;如果有問題,則隨時可以通過開關中心切回老功能邏輯。
優勢和適用場合
優勢:
-
升級切換和回退速度非常快
-
相對於複雜的發佈工具,實施比較簡單,成本相對低廉
-
研發能夠靈活定製發佈邏輯,支持 DevOps 自助發佈
不足:
-
切換是全量的,如果 V2 版本有問題,則對用戶體驗有直接影響;
-
對代碼有侵入,代碼邏輯會變複雜,需要定期清理老版本邏輯,維護成本變高
適用場合:
-
對用戶體驗有一定容忍度的場景
-
已有配置中心或開關中心服務
-
暫不具備研發複雜發佈工具能力;
流量模式
通過功能開關一次完成流量切換,圖片來自附錄 6.1
3.2 A/B 測試
A/B 測試附錄 7.10原來主要用於產品功能的比對測試,收集用戶反饋和對比數據做產品功能設計的決策。實際上,A/B 測試也可以作爲一種新功能發佈技術。下圖展示基於 LB 實現的一種 A/B 測試發佈。
實踐要點
-
上圖中,原來 PC 端和手機端都訪問老版本 V1 服務(也稱 A 組或控制組),當 V2 新版本(也稱 B 組或實驗組)發佈以後,爲了驗證 V2 的功能正確性,同時也爲了避免 V2 有問題時影響所有用戶,先通過 LB 將手機端的流量切換到 V2 版本,經過一段時間的 A/B 比對測試和觀察(主要通過用戶和監控反饋),確保 V2 正常,則通過 LB 將全部流量切換到 V2。
-
基於 LB 方式實現 A/B 測試,LB 需要能夠通過某種條件做流量路由,例如通過 client ip,設備類型,瀏覽器類型,甚至是定製的 HTTP Header 或查詢字符串。
-
高級的 A/B 測試需要專門的平臺支撐,wasabi附錄 6.6就是 intuit 開源的一個支持高級 A/B 測試的平臺,這類平臺可以細粒度到針對某類用戶做 A/B 測試,例如針對某個地區的用戶,某個年齡段的用戶,公司內部用戶等等。舉了例子,假設一個關鍵業務的新功能上線,爲了降低風險採用 A/B 測試,可以做到先只讓公司內部員工能訪問到新功能,待新功能驗證過,再全量放開給外部用戶使用。
-
功能開關和 A/B 測試有點相似,但功能開關一般是無狀態和全量的,無法做到針對某類特定用戶進行測試,而 A/B 測試一般是有狀態的,能夠跟蹤事務和用戶級別的狀態,可以實現針對某類特定用戶進行測試。
優勢和適用場合
優勢:
-
用戶體驗影響小;
-
可以使用生產流量測試;
-
可以做到針對某類特定目標用戶進行測試;
不足:
-
搭建複雜度相對高,有一定技術門檻
適用場合:
-
核心關鍵業務,比如涉及資金的
-
具備一定的 A/B 測試平臺研發能力
流量模式
針對某類目標用戶進行 A/B 測試,圖片來自附錄 6.1
3.3 影子測試
對於一些涉及核心業務的遺留系統的升級改造,爲了確保萬無一失,有一種稱爲影子測試的大招,採用比較複雜的流量複製、回放和比對技術實現。下面是影子測試的一個樣例架構圖,
實踐要點
-
目標實現老的 legacy 服務遷移升級到新的 experimental 服務。
-
測試開始前,需要在測試環境部署一份 legacy 服務和 experimental 服務,同時將生產數據庫複製兩份到測試環境。同時需要將生產請求日誌收集起來,一般可以通過 kafka 隊列收集,然後通過類似 goreplay附錄 6.8這樣的工具,消費 kafka 裏頭的請求日誌,複製回放,將請求分發到 legacy 服務和 experimental 服務,收到響應後進行比對,如果所有響應比對成功,則可以認爲 legacy 服務和 experimental 服務在功能邏輯上是等價的;如果有響應比對失敗,則認爲兩者在功能邏輯上不等價,需要修復 experimental 並重新進行影子測試,直到全部比對成功。根據系統複雜度和關鍵性不同,比對測試時間短的可能需要幾周,長的可達半年之久。
-
影子測試因爲旁路在獨立測試環境中進行,可以對生產流量完全無影響。
-
影子測試一般適用於遺留系統的等價重構遷移,例如.net 轉 Java,或者 SQLServer 數據庫升級爲 MySQL 數據庫,且外部依賴不能太多,否則需要開發很多 mock,測試部署成本會很高,且比對測試更加複雜和不穩定。
-
噹噹網有一個比較成功的交易系統.NET 轉 Java 遷移項目附錄 6.9,採用了影子測試技術,值得參考借鑑。
優勢和適用場合
優勢:
-
對生產用戶體驗完全無影響
-
可以使用生產真實流量進行測試(複製比對)
不足:
-
搭建複雜度很高,技術門檻高,數據庫的導出複製是難點
-
外部依賴不能太多,否則測試部署成本很高,且比對測試更加複雜和不穩定
適用場合:
-
核心關鍵業務,比如涉及資金的
-
具備一定影子測試平臺研發能力,包括流量複製、數據庫導出複製和分發比對系統。
流量模式
影子測試對生產流量無影響,圖片來自附錄 6.1
四、比較
下表對各種發佈策略,從各個維度進行綜合比較,供參考:
五、結論和建議
下面是對發佈策略的一些選型建議,供不同階段公司參考:
-
蠻力發佈一般是不建議採用的,除非是開發測試環境,用戶體驗不敏感的非關鍵應用,或者是創業期什麼都缺時候的無奈之舉。
-
如果暫時還不具備研發較複雜的滾動發佈工具和配套智能 LB,則功能開關是一種不錯的輕量級發佈技術,投入相對較小的成本,可以讓研發人員靈活定製發佈邏輯。
-
金絲雀發佈通過少量新版本服務器接收生產流量的方式去驗證新版本,可以顯著降低風險。金絲雀發佈適用於大部分場景,一般成長型公司就可以採用。
-
對於達到一定業務體量的公司,考慮到用戶體驗對業務的關鍵性,則需要投入研發資源開發支持滾動式發佈的工具和配套的智能 LB,實現自動化和零停機的發佈。滾動式發佈一般和金絲雀發佈配合,先發一臺金絲雀去驗證流量,再按批次增量發佈。
-
隨着輕量級虛擬化(例如容器)的普及,雙服務器組發佈方式具有更快的發佈和回退速度,是值得投入的高級發佈技術。藍綠部署僅適用於雙服務器組,滾動式發佈既可以在單服務器組上實現,也可以在雙服務器組上實現。
-
對於涉及關鍵核心業務的新功能上線,採用 A/B 測試,可以顯著降低發佈風險,A/B 測試是唯一一種支持針對特定用戶組進行生產測試的高級發佈技術。當然 A/B 測試的投入不低,建議有一定研發能力的組織採用。
-
對於關鍵核心業務的遷移重構,爲確保萬無一失,最後的一個大招是影子測試,影子測試對生產流量和用戶完全無影響。當然這個大招的投入成本和門檻都高,建議有足夠業務體量和研發能力的組織投入。
-
上述的各種發佈策略並不是非此即彼的,一個公司常常會綜合採用多種發佈技術作爲互補,實現靈活的發佈能力。例如主流的發佈手段是金絲雀 + 滾動式發佈,某些業務線可能根據業務場景需要採用功能開關發佈,還有一些業務線則可能採用高級的 A/B 測試發佈手段。
六、附錄
-
https://github.com/ContainerSolutions/k8s-deployment-strategies
-
https://opensource.com/article/18/2/feature-flags-ring-deployment-model
-
https://github.com/ctripcorp/apollo
-
http://www.ff4j.org/
-
https://launchdarkly.com/
-
https://github.com/intuit/wasabi
-
https://blog.zenika.com/2017/04/19/migration-dun-legacy-avec-goreplay/
-
https://github.com/buger/goreplay
-
http://blog.shurenyun.com/untitled-9/
-
https://en.wikipedia.org/wiki/A/B_testing