字數總計:0 個 | 閱讀時長:0 分鐘 |閱讀次數: 次
前言
- 前幾章主要討論快速驗證環中「建置階段」的工作
- 本章主要討論如何「高頻」「低風險」地進行軟體部署和發佈,儘早讓軟體在生產環境中執行
- 「高頻」的好處與可能帶來的成本與風險
- 「降低風險」的各種方式:藍綠部署、開關技術…
12.1 高頻發佈是一種趨勢
- 2007年以前,「敏捷軟體開發」的認同度不高,一些傳統IT企業表示:「我們不需要那麼快速地交咐軟體」
- 2009,Flickr 的 John Allspaw 和 Paul Hammond 在 Velocity 2009 年的大會上分享了題目為《Flickr 每天部署10次以上:開發與維運的高效率合作》
- 2011年5月,亞馬遜公司的月度統計顯示,平均每11就觸發一次軟體部署操作,當月最高部署頻率達到每小時1079次之多。平均1萬台伺服器會同時收到部署請求,而最高一次是3萬台伺服器同時執行一個部署操作
- 2017年,Facebook每天對其網站推送多次部署。
高頻發佈的好處
- 有更多機會與真實用戶互動,快速決定或調整自己產品前進的方向
- 每次變更規模較小,降低部署風險
- 單次部署成本降低
- 出現問題易定位、易修復、能快速修正
仍使用低頻發佈模式,強行執行高頻發佈的話,會帶來較高的迭代成本
- 設某團隊以手動模式每個月發佈一次,現改為每週發佈一次
- 假設「仍舊採用原有手動模式部署」,那每個月的工作量就是原來的四倍
12.2 降低發佈風險的方法
高頻帶來好處的同時,也存在各種風險(ex: 工作量提高、錯誤處理…)
藍綠部署
💡 準備兩套完全一致的執行環境,交互作為生產環境與預生產環境,目的為減少釋出過程中服務停止的時間
- 準備兩套完全一致的執行環境
- 一套環境 For 正式生產環境
- 另一套 For 新版本的預生產環境
- 對新版本環境進行驗收測試,直至確認無問題
- 將存取流量引流到新版本所在的環境,作為正式生產環境,同時保持舊版本所在環境不變
- 直至確定新版本沒有問題後,再將舊版本所執行的環境作為下一個新版本的預生產環境,部署未來的新版本
- 很多藍綠部署方案會使用相同的資料庫服務(因為資料庫複製的成本較高)
- 同一個資料庫儲存格式需對新舊兩個軟體版本做相容性處理
- 當切換發生在用戶的一次業務操作過程中且涉及事務處理時,如何處理資料的一致性問題
- 切換發生時尚未返回結果的舊有請求,舊版本環境允許其存取完成
- 之後不再接收新的請求即可
滾動部署
- 從服務群集中選擇一個或多個服務單元,停止服務後執行版本更新
- 相較於藍綠部署,不需要準備兩套一模一樣的服務執行環境,伺服器成本相當於少了一半
- 當新版本出現問題時,這種方式無法像藍綠部署那樣透過前面的流量負載平衡器切回舊環境
- 要對其中已部署新版本的伺服器進行還原
- 或快速修正後發部第三個版本V3,此時服器群集中可能會同時有V1~V3三個版本存在
金絲雀區佈
💡 讓一小部份用戶先行使用新版本,以便提前發現軟體存在的問題
17世紀,礦工帶一隻金絲雀下井。若井下存在有害氣體,在人體還沒察覺到前,金絲雀就會因無法抵抗瓦斯氣體而死亡
灰度發佈
💡 將發佈分成不同的階段,每個階段的用戶數量逐級增加
- 2012 Facebook 發佈一次首頁大改版
- 用戶數達總用戶的1%,網站的瀏覽量、頁面打開率等都有所下降
- 用戶超過10%後,各項關鍵業務仍舊表現不佳
- 於是Facebook 最終放棄這次首頁大改版,恢復了原有的版本
- 兩種實作方式
- 開關隔離方式:設置開關針對不同步圍的用戶開放新功能
- 滾動部署:將軟體的新版本部署到生產環境中的一部分節點上
暗部署
- 為演算法設一個開關
- 當開關打開時,會有流量進入此演算法,但用戶並不知道他用的是舊演算法還是新演算法
- 若此演算法的性能不夠好,可以馬上關閉這個開關
- 流量克隆
- 對每個請求都克隆一份,發送給新演算法
- 但新演算法並不向用戶回饋結果,而是開發人員自己收集資料
12.3 高頻發佈支撐技術
第8章提到,當一個軟體團隊的發佈頻率高於一週一次時,採「主線開發,主線發佈」更為經濟
但當某個功能無法在兩次發佈之間完成開發,怎麼辦?
拆分功能
分解為更小的在一個開發週期內能夠完成的功能集
先後再前
先實作伺服端功能,再實作用戶介面
功能開關技術
透過開關來隱藏未開發完成的功能
- 開關提供兩種用途
- 隔離:將未完成功能的程式隔離在執行路徑之外
- 快速止血:一但生產環境出了問題,直接找到對應功能的開關將其關閉
- 需考慮系統中所有開關的數量和組合測試的問題
- 開關越多,維護成本越高
- 開關存在時間越長,維護成本越高
- 應盡可能少用開關技術
- if else 語句會帶來程式的複雜性,造成程式碼設計混亂
- 模組職責不清時,更容易出錯
- 但如果在「分支」和「開關」間選擇,盡可能選擇開關技術
- 建立分支會帶來後期的分支合入及多次測試成本
- 應對開關設置項目進行統一管理
- 定期檢查和清理不必要的開關項目
- 常見工具
- C/C++: gflag,Google公司貢獻的開源工具
- Java社群可用:Togglz or Flip
- Grails: grails-feature-toggle
- .Net: FeatureToggle
資料移轉技術
因為資料庫更新可能需要較長的時間,停機更新的方式可能不合適,所以處理資料庫的版更時可以選擇:
- 小幅改動的話:
- 只增不刪:欄位盡可能只增不刪
- 大幅資料結構的改變,則資料移轉SOP如下
- 為資料庫結構增加一個新版本
- 修改應用程式,同時向兩個版本的結構中寫入資料
- 編寫腳本程式,以後台服務的方式將原來的歷史資料,回填到新版本的結構中
- 修改應用程式,從新舊兩個版本中讀取資料,並進行比較,確保一致
- 當確認無誤後,修改應用程式,只向新版本結構寫入資料,可以將原來的舊版本資料保留一段時間,以防止未預期的問題出現
抽象分支方法
大型架構變動會需要較長的時間,傳統做法如下圖,以真實分支,大規摹覆寫的方式進行架構調整
這種方式在調整後第一次發佈時出現問題的概率較大,需要一定的品質打磨週期
💡 「抽象分支方法」是在不建立真實分支的情況下,透過設計手段,將大的重構專案分解成很多個小的程式碼變更步驟,逐步完成大的程式碼架構調整。
- 好處:
- 重構的同時也能交付業務功能需求
- 可以逐步驗證架構調整的方向和正確性
- 如果遇到緊急的情況,很容易暫停,且不浪費之前的工作量
- 能強化團隊的合作性
- 可以使軟體架構更模組化,變得更容易維護
- 成本
- 整個修改的時間週期可能會拉長
- 整體工作量比一次性完成的情況要大
- 案例
- iBatis 和 Hibernate 是兩種物件關係映射框架 (Object Relational Mapping,ORM)
- GoCD團隊曾使用抽象分支方法成功將IBatis 替換成Hibernate,並有兩個對外發佈的版本同時包含了這兩個ORM框架
- 在使用抽象分支方法前,也曾嘗試使用從主線上建立分支進行框架替換,但失敗了
- 團隊大多數人在主維上開發功能,分支上做框架替換,每天將主線程式碼同步到分支上
- 原預計三週可以完成的任務,六週也沒有能夠完成
- 如果使用建立分支的方式,通常必須停止大部分的新功能開發,否則很難成功
升級替代還原
- 我們總會遇到部署或發佈後出現一些問題,需要馬上修復
- 此時若有使用開關技術,便重新設置一下開關即可
- 但若沒有使用開關技術,怎麼辦呢? ⇒ 升級替代還原
Facebook的處理方法:
- 盡可能以程式碼升級方式替代binary還原
- 典型的還原操作:將與待修復的問題相關的某次提交,以及與之相關的任何提交一同從程式碼倉庫中直接剔除,然後再次提交,等待下一次發佈即可
- Facebook之所以可以以升級方式替代還原,得益於:
- 其工程師的程式碼提交遵循「小步、獨立、頻繁」的原則
- 發佈頻率高
- Facebook工程師平均每天提交程式碼0.75次,平均每人每天提交約100行程式碼的修改
12.4 影響發佈頻率的因素
- 高頻發佈並非適合所有類型的軟體
- 需隨硬體發佈的嵌入式軟體開發來說,其對外發佈的成本非常高
- 一但軟體出現問題而導致退貨率上升,其損失可能相當高
- 決定軟體的發佈頻率時,需綜合考慮以下影響因素
- 增量發佈帶來的獲益和可行性
- 每次發佈或部署的操作執行成本有多高
- 出現問題的概率與由這些問題帶來的成本有多少
- 維護同一軟體的眾多不同版本帶來的成本
- 高頻發佈模式對工程師的技能要求
- 支撐這種高頻發佈所需要的基礎工具設施與流程完善性
- 組織對這種高頻發佈的態度與文化取向
其中 5、6、7對前面四項的結果會產生直接影響
可能會因這三項原因使高頻發佈的成本高居不下,獲益相對較少
此時企業領導就需做出更多努力,在後面三項上投入更多的精力
推遲發佈動機的漸進壞強環
- 大家習慣推遲風險
- 兩次發佈之間的間隔越長
- 累積的程式碼變更越多
- 所需品質驗證時間就越長,部署成本、發佈風險就越高
12.5 小結
本章討論了
- 如何在快速部署發佈的情況下,透過多種技術手段降底風險
- 資料庫遷移技術
- 各種部署策略
- 藍綠部署
- 金絲雀(灰度)發佈
- 抽象分支部署
- 暗部署
- 應對高頻部署的其它技巧
- 拆分功能、先後再前
- 開關技術
- 資料移轉技術
- 抽象分支方法
- 升級替代還原
- 在某些業務場景下,我們的確無法直接高頻地對外發佈軟體
- 但我們若能使用本章介紹的方法持續向預生產環境進行發佈與部署,就可以儘早獲得軟體的相關品質回饋,進而減少正式發佈後的風險。
- 如果我們能將每次發佈的平均成本降低到足夠低,那麼將會直接改變團隊的產品研發流程