一些微服务拆分的浅见
大家好,我是Z哥。
不管是十幾年前 SOA 的流行,還是 7、8 年前微服務的大行其道,還是如今云原生的展露鋒芒,背后都離不開一件事,程序拆分或者說服務拆分。否則,一個單體應用,以上的這些技術潮流好像都與它沒什么關系,只是一個看客。
雖然Z哥我沒有從頭開始完整地親歷過以上三個時期,但是這三個時期都有過我留下的足跡。所以我想我接下去分享的內容應該對處在云原生時代的大家有所幫助。
/01? 拆分有什么好處/
拆分的目的很容易理解,分而治之。本質是將復雜的大問題分解成更簡單的多個小問題,從而解決它。
而在拆分之前的單體系統中,我們往往面臨著哪些問題呢?
01? 數據庫瓶頸
所有的業務都由一個數據庫承載著,隨著業務的發展,數據庫日常內存吃緊,時不時還搞出個 cpu 90% + 以示它的怒火。
02? 增加人員對開發效率提升的邊際效益遞減
項目里的代碼量從 10 萬行,增長到 100 萬,再到 1000 萬。隨著代碼量的增加,代碼之間的耦合問題越發嚴重,開發效率明顯降低。好吧,效率不夠數量來湊。擴招了更多的人進來,但是發現耦合問題更加嚴重了,經常出現 A 等 B 提交代碼,B等 C 提交代碼,C 等 A 提交代碼的情況……
03? 運維成本指數級增加
隨著項目參與人員的增加,每天發布程序的次數也增加了。可怕的是,代碼量也在增加,導致每次編譯發布的時間也增加了,這對開發效率來說是雙重打擊。每天發布的時間加起來可能就占了半天。
希望你所在的團隊不要處在如此痛苦的場景中。
/02 ?什么時候拆?/
拆分雖好,但也不是萬能的靈丹妙藥。對于大多數組織來說,一個新系統不適合一上來就按照拆分的思路來做。因為拆分需要基于對當前業務、當前系統、當前環境的理解之上的,而面對一個未來充滿未知的新業務,我們當下的信息積累是不夠的,如果過早拆分,很容易導致邊界劃分不合理的情況,這在后續會帶來不小的負面作用。甚至,可能這個產品在經過市場驗證失敗后就被砍了,之前的工作做得再多、再完美,全白費了。
因此相對來說,從一個已有的單體系統中逐步拆分出一個個模塊反而容易得多,因為確定性更高。
單體系統和分布式系統對成本與業務復雜度之間的關系是這樣的。
因此,在這個臨界點附近進行拆分工作的性價比是最高的。
對于如何判斷是否達到了這個臨界點,我認為至少要符合以下三點中的兩點。
業務已在市場站穩腳跟,規劃中業務發展速度未來可能會加速。
開發人員持續擴張,并且未來還將繼續。
平均單人開發效率下降。多個開發人員之間的工作相互影響、依賴,導致解決這些沖突所花費的成本占到了總開發成本的 30%以上。比如,提交的代碼沖突、你等我 coding 完才能繼續 coding 這種(往往這樣的情況下,每個迭代的版本也很大)。
/03? 拆分前的準備工作/
并不是以上條件滿足了就可以拆了。在實際拆分之前,我們要做一些準備工作。這其中最為關鍵的是兩件事:
統一拆分原則
基礎設施建設
因為從單體系統到分布式系統不僅僅是技術的升級,更是開發理念的轉變。
這兩件事的具體就不展開了,前人已經總結過很多了,我就簡單羅列一下。在應用拆分這件事上比較適用的是:
高內聚低耦合
閉包原則
接口隔離
演進思維
避免循環依賴
另外,分布式系統中常用的基礎設施主要是以下這些:
消息隊列
緩存
日志系統
服務治理
監控
網關
配置中心
數據訪問組件
以上這些是必須項,其它可選項還有不少,比如:分布式文件系統、容器管理平臺、CI/CD 等等。
/04? 拆分思路/
具體的拆分其實就是劃分邊界的過程。強烈建議通過 DDD 的思想進行。
深入理解業務,從中定義出隱含的實體、值對象。
從實體對象中找出聚合根,根據實體、值對象與聚合根的依賴關系,建立聚合。
根據業務場景等環境因素,劃分限界上下文。這里的限界上下文就可以與拆分出來的微服務一一對應。
其中最關鍵的是「抽象」工作,為了更易理解還是來舉個例子說一下。比如,當我們在某某養車平臺下單一個保養訂單,你說其中的“安裝”業務該以什么形式進行交易比較合理?Z哥我認為是將其當作一個普通商品看待,當然該平臺也的確是這么做的。如此一來,購買機油機濾和安裝服務對用戶來說是一樣的,很自然地被創建在一筆訂單里,而不是兩筆訂單。
如何評估抽象的好不好呢?可以從以下兩個角度來觀察。
兩個限界上下文之間的依賴應該越少越好。并且依賴的上游不需要知道下游的信息。比如訂單 service 依賴商品 service ,但是商品 service 無需知道訂單 service 的存在。
推演可能的未來業務,如果能響應業務變化(不一定 100%滿足),則證明該抽象是符合未來預期的,可以在一段時間內支撐業務的持續發展。
不過不管怎樣,最終你都在抽象程度、成本、復用性這三者之間平衡。
除此之外,我們還可以根據以下三個維度來進行拆分。
是否經常變動
復用程度的高低
是否有特殊的要求(高性能、安全性等)
好了,總結一下。
這篇呢,Z哥和你分享了我對微服務或者說分布式系統如何拆分的看法。
拆分可以解決單體系統的三個痛點。
數據庫瓶頸。
增加人員對開發效率提升的邊際效益遞減
運維成本指數級增加。
但是拆分也不是越早越好,至少符合以下三點中的兩點。
業務已在市場站穩腳跟,規劃中業務發展速度未來可能會加速。
開發人員持續擴張,并且未來還將繼續。
平均單人開發效率下降。多個開發人員之間的工作相互影響、依賴,導致解決這些沖突所花費的成本占到了總開發成本的 30%以上。比如,提交的代碼沖突、你等我 coding 完才能繼續 coding 這種(往往這樣的情況下,每個迭代的版本顆粒度不得不變得很大)。
然后,拆分前還需要做好兩項準備工作。
統一拆分原則
基礎設施建設
具體實施拆分的思路,建議以 DDD 的思想來進行。
其實任何事都沒有一招鮮吃遍天的方法,隨著業務、技術的發展,我們的拆分思路也需要持續迭代。如果你之前這方面的實戰經驗比較缺乏,不妨從我分享的這些方面入手試試,希望能對你有所幫助。
推薦閱讀:
接手歷史悠久的老項目,干or跑?
如何讓自己更自律
原創不易,如果你覺得這篇文章還不錯,就「點贊」或者「在看」一下吧,鼓勵我的創作 :)
也可以分享我的公眾號名片給有需要的朋友們。
如果你有關于軟件架構、分布式系統、產品、運營的困惑
可以試試點擊「閱讀原文」
總結
以上是生活随笔為你收集整理的一些微服务拆分的浅见的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【Blog.Core开源】快速升级.NE
- 下一篇: MassTransit中RequestR