索引:
一、單服務(wù)器組發(fā)布
1.1 蠻力發(fā)布
1.2 金絲雀發(fā)布(單服務(wù)器組)
1.3 滾動式發(fā)布(單服務(wù)器組)
二、雙服務(wù)器組發(fā)布
2.1 藍(lán)綠發(fā)布(雙服務(wù)器組)
2.2 金絲雀發(fā)布(雙服務(wù)器組)
2.3 滾動式發(fā)布(雙服務(wù)器組)
三、其它發(fā)布方式
3.1 功能開關(guān)發(fā)布
3.2 A/B 測試
3.3 影子測試
四、比較
五、結(jié)論和建議
六、附錄/參考
(著作權(quán)歸作者所有、本次轉(zhuǎn)載非商業(yè)用途、需要轉(zhuǎn)載請聯(lián)系作者。)
根據(jù) 2017 年的 DevOps 發(fā)展報告,高效能組織和低效能組織在軟件交付的效率上有數(shù)量級上的差異。技術(shù)組織的軟件交付能力是一種綜合能力,涉及眾多環(huán)節(jié),其中發(fā)布是尤為重要的環(huán)節(jié)。
作為技術(shù)人員,大家可能聽說過“滾動發(fā)布”和“藍(lán)綠發(fā)布”等術(shù)語,但是很多人并不清楚這些術(shù)語背后的原理。本文試圖總結(jié)當(dāng)前主流的發(fā)布策略,每個的優(yōu)劣,適用性,讓開發(fā)人員特別是架構(gòu)師對現(xiàn)代發(fā)布技術(shù)有一個更為清晰全面的認(rèn)識,讓大家能夠根據(jù)自己的企業(yè)上下文,對發(fā)布策略做出正確的選型和實踐。
一、單服務(wù)器組發(fā)布
先解釋下單服務(wù)器組的概念,早先我們機器資源比較緊張,不像現(xiàn)在云計算和虛擬化(包括容器技術(shù))這么發(fā)達(dá),所以應(yīng)用機器基本是預(yù)先靜態(tài)分配好的(一般由運維負(fù)責(zé)分配),原來應(yīng)用 A 住在這 n 臺機器上,那么下次升級發(fā)布的應(yīng)用 A 也住在這 n 臺機器上,所以稱為單服務(wù)器組發(fā)布方式。
1.1 蠻力發(fā)布
如下圖所示,這種發(fā)布方式比較簡單粗暴,有點像我們傳統(tǒng)的軟件升級方式,主要靠手工完成,先將老版本 V1 全部下掉,再將新版本發(fā)到機器上去。這種方式會引入服務(wù)中斷(停機),在開發(fā)測試環(huán)境是可行的,但對于生產(chǎn)環(huán)境發(fā)布,其會直接影響用戶的使用體驗,這種方式一般是不建議的。
發(fā)布前示圖:
發(fā)布后示圖:
優(yōu)勢和適用場合
優(yōu)勢:
不足:
適用場合:
- 開發(fā)測試環(huán)境/非關(guān)鍵應(yīng)用(用戶影響面小)/初創(chuàng)公司什么都缺,找夜深人靜用戶訪問量小的時間干
流量模式示圖:
蠻力發(fā)布會引入服務(wù)中斷時間(圖片來自附錄 6.1)
1.2 金絲雀發(fā)布(單服務(wù)器組)
在蠻力發(fā)布基礎(chǔ)上的一種簡單改進發(fā)布方式,目前仍然是不少成長型技術(shù)組織的主流發(fā)布方式。單服務(wù)器組下的金絲雀發(fā)布的簡化步驟如下圖所示:
發(fā)布前示圖
先發(fā)一臺金絲雀(示圖)
全部發(fā)完
實踐要點:
- 金絲雀發(fā)布一般先發(fā) 1 臺,或者一個小比例,例如 2% 的服務(wù)器,主要做流量驗證用,也稱為金絲雀 (Canary) 測試(國內(nèi)常稱灰度測試)。以前礦工開礦下礦洞前,先會放一只金絲雀進去探是否有有毒氣體,看金絲雀能否活下來,金絲雀發(fā)布由此得名。簡單的金絲雀測試一般通過手工測試驗證,復(fù)雜的金絲雀測試需要比較完善的監(jiān)控基礎(chǔ)設(shè)施配合,通過監(jiān)控指標(biāo)反饋,觀察金絲雀的健康狀況,作為后續(xù)發(fā)布或回退的依據(jù)。
- 如果金絲測試通過,則把剩余的 V1 版本全部升級為 V2 版本。如果金絲雀測試失敗,則直接回退金絲雀,發(fā)布失敗。
優(yōu)勢和適用場合
優(yōu)勢:
- 用戶體驗影響小,金絲雀發(fā)布過程出現(xiàn)問題只影響少量用戶
不足:
- 發(fā)布自動化程度不夠,發(fā)布期間可引發(fā)服務(wù)中斷
適用場合:
- 對新版本功能或性能缺乏足夠信心
- 用戶體驗要求較高的網(wǎng)站業(yè)務(wù)場景
- 缺乏足夠的自動化發(fā)布工具研發(fā)能力
流量模式:
少量金絲雀先接受流量,再全量發(fā)布,圖片來自附錄 6.1
1.3 滾動式發(fā)布(單服務(wù)器組)
在金絲雀發(fā)布基礎(chǔ)上的進一步優(yōu)化改進,是一種自動化程度較高的發(fā)布方式,用戶體驗比較平滑,是目前成熟型技術(shù)組織所采用的主流發(fā)布方式。單服務(wù)器組下的滾動發(fā)布的簡化步驟如下圖所示:
發(fā)布前
發(fā)布中,先發(fā)一臺金絲雀
發(fā)布中,再發(fā)若干臺
直到全部發(fā)完
實踐要點
- 滾動式發(fā)布一般先發(fā) 1 臺,或者一個小比例,如 2% 服務(wù)器,主要做流量驗證用,類似金絲雀 (Canary) 測試。
- 滾動式發(fā)布需要比較復(fù)雜的發(fā)布工具和智能 LB,支持平滑的版本替換和流量拉入拉出。
- 每次發(fā)布時,先將老版本 V1 流量從 LB 上摘除,然后清除老版本,發(fā)新版本 V2,再將 LB 流量接入新版本。這樣可以盡量保證用戶體驗不受影響。
- 一次滾動式發(fā)布一般由若干個發(fā)布批次組成,每批的數(shù)量一般是可以配置的(可以通過發(fā)布模板定義)。例如第一批 1 臺(金絲雀),第二批 10%,第三批 50%,第四批 100%。每個批次之間留觀察間隔,通過手工驗證或監(jiān)控反饋確保沒有問題再發(fā)下一批次,所以總體上滾動式發(fā)布過程是比較緩慢的 (其中金絲雀的時間一般會比后續(xù)批次更長,比如金絲雀 10 分鐘,后續(xù)間隔 2 分鐘)。
- 回退是發(fā)布的逆過程,將新版本流量從 LB 上摘除,清除新版本,發(fā)老版本,再將 LB 流量接入老版本。和發(fā)布過程一樣,回退過程一般也比較慢的。
- 滾動式發(fā)布國外術(shù)語通常叫“Rolling Update Deployment”。
優(yōu)勢和適用場合
優(yōu)勢:
不足:
發(fā)布工具比較復(fù)雜,LB 需要平滑的流量摘除和拉入能力
適用場合:
- 用戶體驗不能中斷的網(wǎng)站業(yè)務(wù)場景
- 有一定的復(fù)雜發(fā)布工具研發(fā)能力;
流量模式
滾動式發(fā)布,流量平滑過渡,圖片來自附錄 6.1
二、雙服務(wù)器組發(fā)布
隨著云計算和虛擬化技術(shù)的成熟,特別是容器等輕量級虛擬化技術(shù)的引入,計算資源受限和申請緩慢問題已經(jīng)逐步解決,可以做到彈性按需分配。為一次發(fā)布分配兩組服務(wù)器,一組運行現(xiàn)有的 V1 老版本,一組運行待上線的 V2 新版本,再通過 LB 切換流量方式完成發(fā)布,這就是所謂的雙服務(wù)器組發(fā)布方式。
2.1 藍(lán)綠發(fā)布(雙服務(wù)器組)
藍(lán)綠發(fā)布僅適用于雙服務(wù)器組發(fā)布,可以認(rèn)為是對蠻力發(fā)布的一種簡單優(yōu)化發(fā)布方式。簡化過程如下圖所示:

實踐要點
V1 版本稱為藍(lán)組,V2 版本稱為綠組,發(fā)布時通過 LB 一次性將流量從藍(lán)組直接切換到綠組,不經(jīng)過金絲雀和滾動發(fā)布,藍(lán)綠發(fā)布由此得名;
出現(xiàn)問題回退也很直接,通過 LB 直接將流量切回藍(lán)組。
發(fā)布初步成功后,藍(lán)組機器一般不直接回收,而是留一個待觀察期,視具體情況觀察期的時間可長可短,觀察期過后確認(rèn)發(fā)布無問題,則可以回收藍(lán)組機器。
優(yōu)勢和適用場合
優(yōu)勢:
不足:
- 切換是全量的,如果 V2 版本有問題,則對用戶體驗有直接影響;
- 需要兩倍機器資源;
適用場合:
- 對用戶體驗有一定容忍度的場景
- 機器資源有富余或者可以按需分配(AWS 云,或自建容器云)
- 暫不具備復(fù)雜滾動發(fā)布工具研發(fā)能力;
流量模式
藍(lán)綠發(fā)布一次完成流程切換,圖片來自附錄 7.1
2.2 金絲雀發(fā)布(雙服務(wù)器組)
對藍(lán)綠部署的一種簡單優(yōu)化,發(fā)布時先從綠組拉入 1 臺金絲雀,待金絲雀驗證通過再發(fā)全量。對比藍(lán)綠發(fā)布,該發(fā)布方式的優(yōu)勢是有一個生產(chǎn)流量的金絲雀驗證過程,可以減輕 V2 可能有問題的風(fēng)險和影響面。簡化發(fā)布過程如下圖所示:

2.3 滾動式發(fā)布(雙服務(wù)器組)
滾動式發(fā)布是對上面的藍(lán)綠和金絲雀發(fā)布的進一步優(yōu)化,按批次增量滾動發(fā)布,提供更平滑的用戶體驗。
實踐要點
- 發(fā)布前先申請一批新服務(wù)器,數(shù)量一般和 V1 版本相同,將 V2 版本應(yīng)用發(fā)布到新服務(wù)器上。例如如果在 AWS 云上,則可以直接調(diào)用 API 申請一批新 VM,如果用容器云 Kubernetes,則可以直接啟動一批新容器(使用 V2 版本容器鏡像)。
- 一般會先通過 LB 拉入 1 臺 V2 版本的機器,這臺機器也相當(dāng)于金絲雀,用于流量驗證。
- 逐步按批次完成發(fā)布,每批只需要通過 LB 拉入 V2 版本,再拉出對應(yīng)數(shù)量的 V1 版本。批次之間留有觀察間隔,通過手工或監(jiān)控反饋確保沒有問題再繼續(xù)發(fā)布。
- 發(fā)布有問題回退很快,直接通過 LB 將流量切回 V1 即可。
- 完成發(fā)布后,一般 V1 版本要保留觀察以備萬一,比如留 1 天,1 天后沒有問題則回收 V1 機器資源。
優(yōu)勢和適用場合
優(yōu)勢:
- 用戶體驗影響小;
- 升級切換和回退(rollback)速度比單服務(wù)器組滾動發(fā)布要快,LB 切流量即可;
不足:
- 需要兩倍機器資源;
- 發(fā)布工具比較復(fù)雜,LB 需要流量切換能力
適用場合:
- 用戶體驗不能中斷的網(wǎng)站業(yè)務(wù)場景
- 機器資源有富余或者可以按需分配(AWS 云,或自建容器云)
- 有一定的發(fā)布工具研發(fā)能力;
流量模式
滾動式發(fā)布,流量平滑過渡,圖片來自附錄 6.1
三、其它發(fā)布方式
上述都是偏傳統(tǒng)的發(fā)布方式,能覆蓋大部分應(yīng)用發(fā)布場景。針對一些關(guān)鍵新功能的上線發(fā)布,或者一些特定的場景,還有一些特殊的發(fā)布方式。
3.1 功能開關(guān)發(fā)布
利用代碼中的功能開關(guān)(Feature Flag/Toggle/Switch)來控制發(fā)布邏輯,一般不需要復(fù)雜的發(fā)布工具和智能 LB 配合,是一種相對比較低成本和簡單的發(fā)布方式。這種方式也是支持現(xiàn)代 DevOps 理念,研發(fā)人員可以靈活定制和自助完成的發(fā)布方式。
功能開關(guān)的原理如下圖所示:
功能開關(guān)發(fā)布,圖片來自附錄 6.2
實踐要點
- 功能開關(guān)發(fā)布需要一個配置中心或者開關(guān)中心這樣的服務(wù)支持,例如攜程的 Apollo 配置中心附錄 6.3,或者開源的 FF4J附錄 6.4,這些都支持開關(guān)發(fā)布,業(yè)界還有專門的功能開關(guān) SaaS 服務(wù),例如 LaunchDarkly附錄 6.5。通過配置中心,運維或研發(fā)人員可以在運行期動態(tài)配置功能開關(guān)的值。當(dāng)然,功能開關(guān)發(fā)布只是配置中心的一種使用場景,配置中心還能支持其它很多動態(tài)配置場景。
- 功能開關(guān)服務(wù)一般提供客戶端 SDK,方便開發(fā)人員集成。在運行期,客戶端 SDK 會同步最新的開關(guān)值,技術(shù)實現(xiàn)有推方式 (push),也有拉方式 (pull),或者推拉結(jié)合方式。
- 新功能(V2 new feature)和老功能(V1 old feature)住在同一套代碼中,新功能隱藏在開關(guān)后面,如果開關(guān)沒有打開,則走老代碼邏輯,如果開關(guān)打開,則走新代碼邏輯。技術(shù)實現(xiàn)上可以理解為一個簡單的 if/else 邏輯。
- 應(yīng)用上線后,開關(guān)先不打開,然后運維或研發(fā)人員通過開關(guān)中心打開新功能,經(jīng)過流量驗證新功能沒有問題,則發(fā)布完成;如果有問題,則隨時可以通過開關(guān)中心切回老功能邏輯。
優(yōu)勢和適用場合
優(yōu)勢:
- 升級切換和回退速度非常快
- 相對于復(fù)雜的發(fā)布工具,實施比較簡單,成本相對低廉
- 研發(fā)能夠靈活定制發(fā)布邏輯,支持 DevOps 自助發(fā)布
不足:
- 切換是全量的,如果 V2 版本有問題,則對用戶體驗有直接影響;
- 對代碼有侵入,代碼邏輯會變復(fù)雜,需要定期清理老版本邏輯,維護成本變高
適用場合:
- 對用戶體驗有一定容忍度的場景
- 已有配置中心或開關(guān)中心服務(wù)
- 暫不具備研發(fā)復(fù)雜發(fā)布工具能力;
流量模式
通過功能開關(guān)一次完成流量切換,圖片來自附錄 6.1
3.2 A/B 測試
(附錄 7.10)原來主要用于產(chǎn)品功能的比對測試,收集用戶反饋和對比數(shù)據(jù)做產(chǎn)品功能設(shè)計的決策。實際上,A/B 測試也可以作為一種新功能發(fā)布技術(shù)。
下圖展示基于 LB 實現(xiàn)的一種 A/B 測試發(fā)布

實踐要點
- 上圖中,原來 PC 端和手機端都訪問老版本 V1 服務(wù)(也稱 A 組或控制組),當(dāng) V2 新版本(也稱 B 組或?qū)嶒灲M)發(fā)布以后,為了驗證 V2 的功能正確性,同時也為了避免 V2 有問題時影響所有用戶,先通過 LB 將手機端的流量切換到 V2 版本,經(jīng)過一段時間的 A/B 比對測試和觀察(主要通過用戶和監(jiān)控反饋),確保 V2 正常,則通過 LB 將全部流量切換到 V2。
- 基于 LB 方式實現(xiàn) A/B 測試,LB 需要能夠通過某種條件做流量路由,例如通過 client ip,設(shè)備類型,瀏覽器類型,甚至是定制的 HTTP Header 或查詢字符串。
- 高級的 A/B 測試需要專門的平臺支撐,wasabi附錄 6.6就是 intuit 開源的一個支持高級 A/B 測試的平臺,這類平臺可以細(xì)粒度到針對某類用戶做 A/B 測試,例如針對某個地區(qū)的用戶,某個年齡段的用戶,公司內(nèi)部用戶等等。舉了例子,假設(shè)一個關(guān)鍵業(yè)務(wù)的新功能上線,為了降低風(fēng)險采用 A/B 測試,可以做到先只讓公司內(nèi)部員工能訪問到新功能,待新功能驗證過,再全量放開給外部用戶使用。
- 功能開關(guān)和 A/B 測試有點相似,但功能開關(guān)一般是無狀態(tài)和全量的,無法做到針對某類特定用戶進行測試,而 A/B 測試一般是有狀態(tài)的,能夠跟蹤事務(wù)和用戶級別的狀態(tài),可以實現(xiàn)針對某類特定用戶進行測試。
優(yōu)勢和適用場合
優(yōu)勢:
- 用戶體驗影響小;
- 可以使用生產(chǎn)流量測試;
- 可以做到針對某類特定目標(biāo)用戶進行測試;
不足:
- 搭建復(fù)雜度相對高,有一定技術(shù)門檻
適用場合:
- 核心關(guān)鍵業(yè)務(wù),比如涉及資金的
- 具備一定的 A/B 測試平臺研發(fā)能力
流量模式
針對某類目標(biāo)用戶進行 A/B 測試,圖片來自附錄 6.1
3.3 影子測試
對于一些涉及核心業(yè)務(wù)的遺留系統(tǒng)的升級改造,為了確保萬無一失,有一種稱為影子測試的大招,采用比較復(fù)雜的流量復(fù)制、回放和比對技術(shù)實現(xiàn)。
下面是影子測試的一個樣例架構(gòu)圖:

實踐要點
- 目標(biāo)實現(xiàn)老的 legacy 服務(wù)遷移升級到新的 experimental 服務(wù)。
- 測試開始前,需要在測試環(huán)境部署一份 legacy 服務(wù)和 experimental 服務(wù),同時將生產(chǎn)數(shù)據(jù)庫復(fù)制兩份到測試環(huán)境。同時需要將生產(chǎn)請求日志收集起來,一般可以通過 kafka 隊列收集,然后通過類似 goreplay附錄 6.8這樣的工具,消費 kafka 里頭的請求日志,復(fù)制回放,將請求分發(fā)到 legacy 服務(wù)和 experimental 服務(wù),收到響應(yīng)后進行比對,如果所有響應(yīng)比對成功,則可以認(rèn)為 legacy 服務(wù)和 experimental 服務(wù)在功能邏輯上是等價的;如果有響應(yīng)比對失敗,則認(rèn)為兩者在功能邏輯上不等價,需要修復(fù) experimental 并重新進行影子測試,直到全部比對成功。根據(jù)系統(tǒng)復(fù)雜度和關(guān)鍵性不同,比對測試時間短的可能需要幾周,長的可達(dá)半年之久。
- 影子測試因為旁路在獨立測試環(huán)境中進行,可以對生產(chǎn)流量完全無影響。
- 影子測試一般適用于遺留系統(tǒng)的等價重構(gòu)遷移,例如.net 轉(zhuǎn) Java,或者 SQLServer 數(shù)據(jù)庫升級為 MySQL 數(shù)據(jù)庫,且外部依賴不能太多,否則需要開發(fā)很多 mock,測試部署成本會很高,且比對測試更加復(fù)雜和不穩(wěn)定。
- 當(dāng)當(dāng)網(wǎng)有一個比較成功的交易系統(tǒng).NET 轉(zhuǎn) Java 遷移項目附錄 6.9,采用了影子測試技術(shù),值得參考借鑒。
優(yōu)勢和適用場合
優(yōu)勢:
- 對生產(chǎn)用戶體驗完全無影響
- 可以使用生產(chǎn)真實流量進行測試(復(fù)制比對)
不足:
- 搭建復(fù)雜度很高,技術(shù)門檻高,數(shù)據(jù)庫的導(dǎo)出復(fù)制是難點
- 外部依賴不能太多,否則測試部署成本很高,且比對測試更加復(fù)雜和不穩(wěn)定
適用場合:
- 核心關(guān)鍵業(yè)務(wù),比如涉及資金的
- 具備一定影子測試平臺研發(fā)能力,包括流量復(fù)制、數(shù)據(jù)庫導(dǎo)出復(fù)制和分發(fā)比對系統(tǒng)。
流量模式
影子測試對生產(chǎn)流量無影響,圖片來自附錄 6.1
四、比較
下表對各種發(fā)布策略,從各個維度進行綜合比較,供參考:

五、結(jié)論和建議
下面是對發(fā)布策略的一些選型建議,供不同階段公司參考:
- 蠻力發(fā)布一般是不建議采用的,除非是開發(fā)測試環(huán)境,用戶體驗不敏感的非關(guān)鍵應(yīng)用,或者是創(chuàng)業(yè)期什么都缺時候的無奈之舉。
- 如果暫時還不具備研發(fā)較復(fù)雜的滾動發(fā)布工具和配套智能 LB,則功能開關(guān)是一種不錯的輕量級發(fā)布技術(shù),投入相對較小的成本,可以讓研發(fā)人員靈活定制發(fā)布邏輯。
- 金絲雀發(fā)布通過少量新版本服務(wù)器接收生產(chǎn)流量的方式去驗證新版本,可以顯著降低風(fēng)險。金絲雀發(fā)布適用于大部分場景,一般成長型公司就可以采用。
- 對于達(dá)到一定業(yè)務(wù)體量的公司,考慮到用戶體驗對業(yè)務(wù)的關(guān)鍵性,則需要投入研發(fā)資源開發(fā)支持滾動式發(fā)布的工具和配套的智能 LB,實現(xiàn)自動化和零停機的發(fā)布。滾動式發(fā)布一般和金絲雀發(fā)布配合,先發(fā)一臺金絲雀去驗證流量,再按批次增量發(fā)布。
- 隨著輕量級虛擬化(例如容器)的普及,雙服務(wù)器組發(fā)布方式具有更快的發(fā)布和回退速度,是值得投入的高級發(fā)布技術(shù)。藍(lán)綠部署僅適用于雙服務(wù)器組,滾動式發(fā)布既可以在單服務(wù)器組上實現(xiàn),也可以在雙服務(wù)器組上實現(xiàn)。
- 對于涉及關(guān)鍵核心業(yè)務(wù)的新功能上線,采用 A/B 測試,可以顯著降低發(fā)布風(fēng)險,A/B 測試是唯一一種支持針對特定用戶組進行生產(chǎn)測試的高級發(fā)布技術(shù)。當(dāng)然 A/B 測試的投入不低,建議有一定研發(fā)能力的組織采用。
- 對于關(guān)鍵核心業(yè)務(wù)的遷移重構(gòu),為確保萬無一失,最后的一個大招是影子測試,影子測試對生產(chǎn)流量和用戶完全無影響。當(dāng)然這個大招的投入成本和門檻都高,建議有足夠業(yè)務(wù)體量和研發(fā)能力的組織投入。
- 上述的各種發(fā)布策略并不是非此即彼的,一個公司常常會綜合采用多種發(fā)布技術(shù)作為互補,實現(xiàn)靈活的發(fā)布能力。例如主流的發(fā)布手段是金絲雀 + 滾動式發(fā)布,某些業(yè)務(wù)線可能根據(jù)業(yè)務(wù)場景需要采用功能開關(guān)發(fā)布,還有一些業(yè)務(wù)線則可能采用高級的 A/B 測試發(fā)布手段。
六、附錄/參考:
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