再談特性切換

weixin_33806914發表於2016-02-04

據ThoughtWorks顧問Pete Hodgson介紹,按照使用時長和動態性進行分類,並以此為基礎實現恰當的特性切換,有助於應對運維複雜性。他在博文中擴充套件了Martin Fowler的特性切換模式,並提出了釋出、ops、試驗和許可權四類特性切換實現策略。在大型專案中,持續交付的困難需要特性切換來克服。

\\

Pete寫道,“特性切換是一項功能強大的技術,允許團隊修改系統行為,而無需改變程式碼”。他提供了一個動態特性切換的簡單示例:

\\
\function reticulateSplines() {\  if( featureIsEnabled(\"use-new-SR-algorithm\") ) {\    return enhancedSplineReticulation();\  } else {\    return oldFashionedSplineReticulation();\  }\}\
\\

在上面的例子中,featureIsEnabled()方法呼叫的位置就是Pete所說的決策點或切換點,該方法實現了一個簡單的切換路由,通常是基於一個簡單的配置檔案(切換配置)來實現。高階特性切換可能會考慮切換上下文,並實現“使用者群(將使用者分組,一項特性對有的組總是開啟,對有的組總是關閉)的概念”。

\\

37dca2b3e4f7345d2f8193e09cca2da6.png

\\

圖片來源:http://martinfowler.com/articles/feature-toggles.html

\\

作者提出了以下幾種不同的切換型別:

\\
  • 釋出類切換將部署從釋出功能中分離出來,是暫時性的。它們常常用於金絲雀釋出策略。“產品經理也可能會使用這個方法——不過是一個以產品為中心的變體——防止只完成了一半的產品特性暴露給終端使用者。”它們可以用作特性分支的替代方案,在後一種情況下,太晚將分支特性合併到釋出版本已被證實是一項複雜的任務。\\t
  • Ops類切換是對源於Netflix Hystrix實現斷路器模式的一種推廣。這類切換會在運維層面修改系統,可以用於在高負載情況下優雅地停用某項服務。\\t
  • 試驗類切換是短期切換,可以用於市場營銷目的的A/B測試。在這種情況下,“系統的每個使用者都被歸入一個使用者群,在執行時,切換路由會根據使用者所在的群始終如一地將特定使用者導向一個或另一個程式碼路徑。”通過評估不同使用者群的群體行為可以評價特性的效果。\\t
  • 許可權類切換主要是長期的可選特性開關,可以用於實現定價策略,比如一個付費模型,針對白銀、黃金或鉑金產品層級。這類切換需要一種比簡單的if/then/else語句更健壯的實現以提高可維護性。\

下面基於使用時長和動態性兩個維度繪製的切換分類圖:

\\

1eff4c3c13229f4cdada1737aa7ed3c6.png

\\

圖片來源:http://martinfowler.com/articles/feature-toggles.html

\\

此外,Martin Fowler將特性切換分為構建時切換和執行時切換。構建時切換可以作為執行時釋出類切換的一種靜態替代方案,藉此,哪一項特性進入釋出是在編譯期間決定的。在各種Agile Release Trains中,釋出構建遵循一個固定的時間表。測試過的特性可以進入釋出序列,而未完成或不穩定的特性在構建時會被排除在外。金絲雀微服務部署是另一種可以實現分離的可選方法。

\\

Pete認為,“隨著時間的推移,特性切換有一種越來越普及的趨勢”。他提出了以下幾項特性切換實現原則:

\\
  • 運用策略模式避免切換點條件語句,而將if/then/else語句封裝到路由層。\\t
  • 引入實現決策邏輯的決策物件,將決策點從決策邏輯中分離出來。這樣,舉例來說,特性分組變化不會破壞程式碼。\\t
  • 把決策物件作為建構函式引數注入,將程式碼從特性切換基礎結構中分離出來,以便可以用它切換任何想要切換的方法。這樣,程式碼設計就可以不考慮切換路由,簡化了開發測試。\

Pete繼續討論了不同的切換配置選項。雖然有些釋出類切換可以在應用程式啟動時啟用或禁用,但其他切換需要在執行時重新進行配置,比如ops類切換,同時,試驗類切換和許可權類切換則在每個使用者會話甚或每次請求時發揮作用。作者建議使用靜態配置作為特性切換配置的首選模式,因為一旦配置作為程式碼正確完成,就可以對它進行版本控制,並將其視為程式碼(審查、部署等等)。對於高階設定,他建議使用諸如Consul、etcd或Zookeeper這樣的分散式鍵-值儲存。

\\

特性切換在大型專案持續交付管道中變得越來越重要,因為它們有助於將部署從釋出中分離出來。協調分支合併以及並行向公共環境釋出特性使團隊必須序列化任務,導致速度下降。通過消除全是或全否的釋出策略,特性切換幫助恢復了團隊所需要的速度,雖然這是有成本的。除了會增加運維複雜度外,特性切換還會廣泛引入其他的風險,尤其是使用釋出類切換遮蔽未完成的程式碼時。據Jim Bird介紹,特性切換會導致“程式碼更脆弱、更難測試、更難理解和維護、更難提供技術支援,而且更不安全。”他的主要論據是,將未經測試的程式碼引入生產環境是一個糟糕的主意,它們可能會在無意間暴露出來。他舉了一家金融機構因為這種情況破產的案例。“特性切換需要一個魯棒的工程過程、可靠的技術設計和成熟的特性切換生命週期管理。不具備這三個關鍵的條件,使用特性切換就是反生產力的。”

\\

風險暫且擱置,Facebook在最近的一篇論文中探討了特性切換在Web規模下的應用。Facebook的實現嚴重依賴特性切換。他們使用的不是基於配置的切換,而是基於規則的切換。一款名為Gatekeeper的UI管理工具用於啟用特性,它運用一種靈活的選擇過濾方法劃分使用者群。那樣,特性就可以暴露給根據人口統計學和其他引數選出的使用者:“起初,Gatekeeper可以只對開發這個特性的工程師開放該產品特性。然後,Gatekeeper可以向更大比例的Facebook員工開發該特性,比如從1%到10%再到100%。在內部測試成功後,它可以向某個特定區域內5%的使用者開放。最後,該特性可以逐步在全球推出,比如,覆蓋範圍從1%到10%再到100%。”,論文作者這樣解釋道。

\\

d1e62d7c3cf74eb9a413e0b20fc49ab7.png

\\

圖片來源:http://abhishek-tiwari.com/post/decoupling-deployment-and-release-feature-toggles

\\

Pete的博文是分期釋出的,後續還會發布更多內容。

\\

檢視英文原文:Feature Toggles Revisited