前不久參加2016年QCon,針對 "服務架構演進" 的有所感悟,會後針對演進各階段的特點彙總如下。
階段一:單體應用(Monolith Application)
這是早期的Wed應用開發方式,通常MVC層、Service層和ORM層整合在同一個Web應用中,在遭遇流量壓力時,只能進行簡單的機器集羣。一個典型單體應用結構如下圖所示:
概念:將應用程序的所有功能都打包成一個獨立的單元,可以是JAR、WAR、EAR或其它歸檔格式。
優點 | 解釋 |
---|---|
1、爲人所熟知 | 現有的大部分工具、應用服務器、框架和腳本都是這種應用程序 |
2、IDE友好 | 像NetBeans、Eclipse、IntelliJ這些開發環境都是針對開發、部署、調試這樣的單個應用而設計的;至今沒有一款天然爲遠程服務調用設計的IDE; |
3、便於共享 | 單個項目歸檔文件包含所有功能,便於在團隊之間以及不同的部署階段之間共享; |
4、易於測試 | 單體應用一旦部署,所有的服務或特性就都可以使用了,這簡化了測試過程,因爲沒有額外的依賴,每項測試都可以在部署完成後立刻開始; |
5、容易部署 | 只需將單個歸檔文件複製到單個目錄下,如Tomcat,即可完成部署,不依賴第三方業務; |
伴隨業務發展,缺點之間暴露,複雜而巨大的單體式應用也不利於持續性開發,缺點如下。
缺點 | 解釋 |
---|---|
1、代碼重複率高 | 各個單體應用,公共模塊重複開發、重複維護; |
2、需求變更困難 | 不夠靈活:對應用程序做任何細微的修改都需要將整個應用程序重新構建、重新部署。開發人員需要等到整個應用程序部署完成後才能看到變化。如果多個開發人員共同開發一個應用程序,那麼還要等待其他開發人員完成了各自的開發。這降低了團隊的靈活性和功能交付頻率;臃腫的部署,整個應用; |
3、妨礙持續交付 | 無法滿足新業務快速創新和敏捷交付:單體應用可能會比較大,構建和部署時間也相應地比較長,不利於頻繁部署,阻礙持續交付。在移動應用開發中,這個問題會顯得尤爲嚴重; |
4、功能孤島 | 傳統的MVC架構、本地代碼不斷迭代、垂直的功能孤島;最終演化成調用關係只有原作者可讀懂,直至腐化失傳;團隊接手困難,單體邏輯複雜; |
5、共生共滅 | 垂直應用越來越多》測試、部署成本高,可伸縮性差, 可靠性差,影響單體應用內其他業務邏輯,共生共滅; |
6、侷限的彈性與擴展能力 | 強耦合的整體;耦合:MVC、Service和ORM層耦合; |
7、阻礙技術革新 | 單體應用技術選型單一;受技術棧限制:對於這類應用,技術是在開發之前經過慎重評估後選定的,每個團隊成員都必須使用相同的開發語言、持久化存儲及消息系統,而且要使用類似的工具,無法根據具體的場景做出其它選擇; |
8、技術債務 | “不壞不修(Not broken,don’t fix)”,這在軟件開發中非常常見,單體應用尤其如此。系統設計或寫好的代碼難以修改,因爲應用程序的其它部分可能會以意料之外的方式使用它。隨着時間推移、人員更迭,這必然會增加應用程序的技術債務。 |
最終,導致以下問題。
那麼,如何解決 “單體應用” 問題呢?
系統需要做到:分層、解耦、拆分、獨立;
階段二:面向服務架構(SOA)
這是目前業界比較流行的架構模式,通常根據業務職責劃分爲多個系統,系統之間的交互以服務的方式進行。
概念:Service-Oriented Architecture,將應用程序的不同功能單元(稱爲服務)通過這些服務之間定義良好的接口和契約聯繫起來。
通常需要接入RPC中間件,如Dobbo、Thrift等;
優點 | 解釋 |
---|---|
1、分層 | 抽象核心服務和業務服務等,形成公共服務; |
2、獨立 | 服務可以獨立打包、發佈、部署 |
3、服務可伸縮 | 可以有針對性的進行單個服務的擴容; |
4、專注性 | 屏蔽底層複雜度 |
5、資源重用 | 提供有限接口,無限性能; |
6、系統解耦 | 不同業務功能拆分不同系統,避免耦合; |
7、透明調用 | 封裝底層通訊細節,向調用本地方法一樣調用遠程服務; |
8、SQL 質量得到保障 | 有了服務層之後, 所有的 SQL 都是服務層提供的,業務線不能再爲所欲爲了 |
9、數據庫解耦 | 底層例如數據庫連接到達上限系統共用的底層資源在隨着機器增加的越來越多時,一定會成爲瓶頸,這種情況下服務化會帶來幫助 |
10、敏捷交付 | 開發人員規模龐大當開發人員規模變大(100個左右)時,衆多人共同維護一個系統會變得不可行,這個時候服務化可以產生巨大幫助,也會成爲必須做的事情。 |
雖然SOA解決了單體服務的痛斷,但是又引入許多新的問題,如下:
缺點 | 服務化不是銀彈!警惕“單體服務”! |
---|---|
1、耦合部署 | 單體服務內部,各個服務在代碼、發佈時耦合; |
2、運維效率低 | 一個需求設計多個項目,需要發佈多個項目; |
3、提升系統複雜度 | 服務註冊發現、限流、降級(熔斷)、故障隔離等; |
4、服務依賴 | 業務穩定性依賴第三方服務; |
5、學習成本 | 存在一定上手難度 |
6、時延問題 | 服務通訊增加了額外的系統負責度,以及性能開銷; |
7、問題定位 | 分佈式環境,高效快速定位問題 |
8、事務一致性 | 邏輯關聯的幾個連續數據庫操作被打散在不同服務中,最終一致性,消息加輪訓,try-confirm-cancel; |
9、難以重構 | RPC私有協議,並非瀏覽器友好, |
10、多團隊進度協同問題 | 需要等待以來的服務方提供服務API纔可以進行開發 |
11、接口前向兼容性問題 | 服務以API方式發佈,必須要兼容老版本API不受影響 |
12、基礎設施&團隊要求高 | 企業的基礎設施以及團隊要求也比較高 |
當SOA帶來的上述問題越來越尖銳時,同樣將導致一些結果:
那個該如何解決上述問題呢?
需要我們進行 “有效的服務拆分”
階段三:微服務(Micro Services)
我們重點關注標紅的部分:一系列小服務、各自運行在單獨的進程、圍繞各自業務功能、獨立部署、最低限度的集中管理;
概念/優點 | 解釋 |
---|---|
1、有效拆分 | 有效的拆分應用,實現敏捷開發和部署; |
2、獨立部署(服務自治) | 將應用程序設計成一套可以單獨部署的服務。原子粒度:服務拆分粒度:SOA首先要解決的是異構應用的服務化;微服務強調的是服務拆分儘可能小,最好是獨立的原子服務; |
3、避免依賴 | 傳統的SOA服務,由於需要重用已有的資產,存在大量的服務間依賴;微服務的設計理念是服務自治、功能單一獨立,避免依賴其它服務產生耦合,耦合會帶來更高的複雜度; |
4、敏捷運維 | 傳統SOA服務粒度比較大,多數會採用將多個服務合併打成war包的方案,因此服務實例數比較有限;微服務強調儘可能拆分,同時很多服務會獨立部署,這將導致服務規模急劇膨脹,對服務治理和運維帶來新的挑戰; |
5、敏捷交付 | 服務由小研發團隊負責微服務設計、開發、測試、部署、線上治理、灰度發佈和下線,運維整個生命週期支撐,實現真正的DevOps。 |
服務化雖然擁有以上優點,但是萬物具有兩面性,同樣會帶來以下問題:
缺點 | 微服務不是銀彈! |
---|---|
1、服務數量激增 | 微服務化之後,服務數量的激增會引起架構質量屬性的變化; |
2、調用鏈路變長 | 服務拆分粒度更小必然導致調用鏈變長,遠程服務通訊次數更多 |
3、服務監控複雜 | 調用鏈增長,需要監控的調用鏈更長 |
4、基礎設置 | 爲了保證高性能、低時延,需要高性能的分佈式服務框架保證微服務架構的實施;自研服務框架還是使用開源的方案; |
5、遷移成本,人員技能培訓成本 | 評估遷移的工作量,以及人員技能培訓等 |
6、適用範圍 | 當前單機應用是否能夠滿足業務發展需要,有沒有必要做服務化改造和分佈式部署; |
微服務拆分粒度:
- 1、功能完整、職責單一,這是理想的拆分原則,但是完全按照功能拆分,可能會導致服務數量激增,需要權衡得失;
- 2、粒度適中,團隊可接受:這是推薦的拆分原則,通常一個微服務對應一個業務開發團隊,在團隊業務內適當放寬粒度可以提高開發效率和體驗;
從上文總結,微服務演進經歷有 "單體應用 》 服務化 》 微服務" 等流程,如下圖所示:
參考
- 《電商 CRM 的微服務重構實踐》阿里巴巴客戶體驗事業羣高級技術專家 邱小俠
- 《大型企業雲平臺架構和關鍵技術實踐》華爲軟件雲平臺資深架構師 苗彩霞
- 《滴滴代駕微服務架構演進》滴滴代駕事業部架構師 趙偉
- http://www.tuicool.com/articles/Qr2q6z3
- http://www.infoq.com/cn/news/2015/04/single-app-micro-service/
- https://my.oschina.net/zhanghaiyang/blog/725728