淺談微服務架構設計

2021-02-25 java進階架構師

★★★建議星標我們★★★

公眾號改版後文章亂序推薦,希望你可以點擊上方「Java進階架構師」,點擊右上角,將我們設為星標」!這樣才不會錯過每日進階架構文章呀。


架構定義是一門技術,但更是一門藝術。微服務架構是基於分而治之的思想演化出來的。過去傳統的一個大型而又全面的系統,隨著網際網路的發展已經很難滿足市場對技術的需求,於是我們從單獨架構發展到分布式架構。

微服務架構是一種架構模式,它提倡將單一應用程式劃分成一組小的服務,服務之間互相協調、互相配合,為用戶提供最終價值。

關於微服務架構設計呢?簡單來說可分為下面三個步驟:

第一步,把應用中關鍵的需求定義出來;

第二步,識別出採用微服務架構時應用中所包含的所有服務;

第三步,將第一步所定義出的關鍵需求作為架構需求的場景來描述服務之間如何進行協作。這個步驟很像單體架構下我們所做的系統高層架構設計,通過高層架構設計會識別並定義出各個業務領域模型,這些業務領域模型包含了業務對象的關鍵操作流程,通過這些業務領域模型就可以輔助我們規劃出整個應用架構,即各模塊之間的協作關係。

在識別應用中的服務時,應首先專注於業務,通過業務邏輯的視角可以快速有效地將核心微服務識別出來。核心微服務識別出來之後,就可以圍繞核心服務把相關聯的服務都定義出來,並可以對這些服務進行分組、合併處理,最終完整定義出應用的一系列微服務。切記,不可以一開始從技術的角度去拆分,否則由於業務之間的關聯關係很有可能會將設計出來的微服務拉入「焦油坑」中。

當識別出應用的每一個微服務後,我們就需要考慮這些微服務之間如何進行協作。定義各個微服務之間協作關係最有效的方式就是根據每一個業務進行分析。

有些業務場景可能只需要某一個服務就可以完成,有些業務場景則可能需要兩個或多個服務才可以。這些協作可能是實時同步的,也可能是異步執行,我們可以根據這些具體需求來確定使用何種方式進行交互(是使用REST、RPC,還是消息)。此外,還有一個需要我們第一時間去考慮的問題就是用戶的服務請求最初是由哪個服務承擔的。

可能我們在接觸微服務架構之初,一腔熱血看哪個都可以作為一個微服務,最終將系統中的每一個部分都拆分成了一個微服務。但如果是這樣,我們所設計的微服務粒度將太過細,每一個微服務可能只實現了數據處理,而業務處理需要粘合過多的代碼才能夠讓這些微服務整合來完成一個具體的業務處理,反而造成了更加複雜的系統,明顯不合理。對於設計微服務來說,最好的方式是先專注於各個服務之間的交互,先把它們劃分成粗顆粒度的服務,然後隨著系統的升級和功能的提升,再將這些粗顆粒度的服務逐漸細化,形成更為合理的微服務粒度。隨著應用功能需求的增加或變化,原來的一個微服務中所承擔的責任也在增加,當我們發現在一個微服務中已經承擔了多種職責的話,這個時候就是考慮對微服務進行拆分的最佳時機。那麼如何衡量我們所設計的微服務粒度是否合適呢?對於過於粗粒度的微服務來說,該微服務一定承擔了太多的職責,往往在服務中塞了過多的業務邏輯和業務規則,而且業務流程也非常複雜,難以理解(常常會讓你感覺好像還是在開發單體系統一樣)。對於粗粒度的微服務另一個明顯的表現就是擁有眾多數據的管理權限。對於一個粒度合適的微服務來說,其所管轄的數據也是有限的,一旦某個微服務所管轄的數據眾多,並且這些數據之間也沒有合適的業務關聯,那麼顯然該微服務粒度太粗了,需要進行細化。反之,如果所設計的微服務顆粒度太細,一個明顯的標誌就是每一個微服務幾乎都需要和其他的微服務進行溝通,每個微服務只承擔其中很少量的業務處理,然後就交給其他微服務處理,造成了一個外部請求需要經過太多的微服務才能夠完成處理。當你想單拎出一個服務時,發現幾乎不可能,因為每一個微服務都依賴於其他微服務,同時又被其他微服務所依賴。微服務架構的設計一定是與時俱進的,因此我們也不可能在第一次設計時就設計出一個完美的架構體系。因此,在最初構建粗顆粒度的服務要優於過細的微服務,因為粗粒度的微服務會隨著系統升級而逐漸細化形成粒度合適的微服務,而過細的微服務在構建和管理上非常複雜,也難以重構、合併成合適的大小。此外,也不要太過糾結教條式的設計規約,在開始時甚至可以允許兩個微服務之間的數據進行相互處理和聚合,因為對於許多業務對象之間畢竟並沒有一個清晰的界限。還是那句話:實踐出真知,只有你行動了,開始著手讓微服務「跑」起來了,終究有一天會找到那個合適你的微服務架構方案,否則即使討論百遍也得不到。微服務架構的開發尚處於「蠻荒」時代,並沒有一些成型的指導原則和模式供我們參考,但是我們可以從面向對象的開發理論中進行借鑑。Robert C.Martin在《敏捷軟體開發:原則、模式與實踐》一書中提出了面向對象開發的一系列原則與模式,其中有以下兩個原則可以在微服務拆分的時候借鑑:單一職責原則(Single Responsibility Principle,SRP):一個類應該有且只有一個變化的原因。
There should never be more than one reason for a class to change

我們在開發的時候深有體會,每一個職責都是一個變化引起類變化的中心。當功能變化時,通常需要通過更改相關的類來實現。如果一個類擁有多個職責,那麼就會有多於一個原因來導致這個類的變化。另外,一個類承擔多個職責後,往往這些職責就會耦合在一起,某一職責的改變可能會影響到其他的職責。這樣的類設計是非常脆弱的,從而會導致應用的穩定性。因此,我們在進行類設計時要遵守單一職責原則。
同樣,對於微服務設計來說,如果一個微服務承擔太多職責的話,也會導致微服務業務之間的耦合,為業務進行改變時埋下了不穩定因素。所以,單一職責原則同樣也適用於微服務設計,我們可以將微服務保持足夠小,僅擁有一個業務職責,保持微服務的業務單一性,從而提升應用的穩定性。共同封閉原則(Common Closure Principle,CCP):包中的所有的類對於同一種性質的變化應該是共同封閉的。一個變化若對一個封閉的包產生影響,則將對該包中的所有類產生影響,而對其他包則不造成任何影響。
The class in package should be closed together against the same kinds of changes. A change the affects a package affects all the classes in that package

簡單來說,共同封閉原則是延伸了面向對象開發中六大原則之一的開閉原則(OCP)中的關閉概念。就是說當需要修改某項業務時,我們需要將修改的範圍限制在同一個包內,而不是遍布在很多包中。共同封閉原則指導我們如何對類進行有效的組織,將那些在業務概念上聯繫得非常緊密、通常一起發生改變的類,封裝到同一個包中。通過共同封閉原則可以提升對應用組織上的管理。同樣,通過使用共同封閉原則可以將那些在業務上聯繫緊密,由於同一個原因而改變的服務組織在一個微服務中。這樣一方面我們可以減少微服務的數量,另外一方面當業務發生改變時我們只需要一個業務開發團隊進行單獨修改,只需要重新部署該服務即可,減少了不同微服務開發團隊之間溝通成本。一個團隊越大,那麼溝通與協助成本就會越高。因此,在微服務治理中有一個重要的理念就是自治,自治範圍並不只是代碼和數據,還包含微服務的運行和維護管理,所以亞馬遜的微服務有一個規則:你構建,你運行。將微服務分而治之的另一個重要方面是數據管理的分而治之。傳統單體架構應用的開發在很多時候多個業務之間的數據交互是直接通過操作資料庫來完成,當需要更改某一業務資料庫表時往往會涉及多個模塊,甚至有時候根本不清楚修改這張資料庫表到底會影響到多少業務代碼,從而不敢動資料庫表的定義,只好退而求其次,通過增加表來處理,進而加劇了系統架構的惡化。雖然現在O/R mapping技術的出現從一定程度上解決了這個頭痛的問題,但終未從根本上解決。而微服務中的分而治之理念,不但是指業務功能,也同時包含了對業務數據的管理。將業務數據管理進行私有化之後就進一步降低了業務之間的耦合度,所以實施微服務的架構師,一定要保持業務數據管理的私有化,即使你在項目中不能夠分庫,也要牢記這條規則,嚴格要求各微服務團隊看好自己的數據。微服務架構中的數據自治是指每個微服務擁有其業務領域對象下的數據,只有該微服務可以對這些數據進行操作(包含讀取與更改),而其他微服務只有通過該服務才能訪問到這些數據,不能直接通過資料庫進行溝通。因此,我們可以不用為每一個微服務創建一個獨立資料庫,可以將它們統一存放在一個資料庫中,保障不破壞上述的數據訪問原則即可。當我們開始使用微服務架構進行開發時,一個清晰明了、規範的交互方式將極大提升應用開發效率。通常,我們可以使用以下原則作為微服務接口設計的準則。使用REST協議:REST可以說在微服務互相調用之間起著非常重要的角色,強烈建議大家使用HTTP作為服務的調用協議,並在服務處理上使用HTTP標準動詞(GET、PUT、POST和DELETE)。使用URI表達:服務端點的URI應該能夠清晰表達出我們所要解決的問題、提供的方法、相應資源信息及資源之間的關聯關係。使用JSON數據格式:JSON作為輕量級數據格式協議,及自帶的序列化和反序列化機制,幾乎已經成為通信中的數據標準協議,並且對於前端開發來說非常容易使用與整合。使用HTTP標準狀態碼:HTTP協議本身具有非常豐富的狀態碼,那麼使用這些狀態碼來作為服務調用結果的狀態是非常合適的。以上準則,總結起來就是讓所設計的微服務接口更清晰,更容易讓其他開發者掌握和使用。將單體架構應用遷移到微服務架構意味著一個漫長的過程,不過這和在開發時經常做的代碼重構類似,只是變成了對架構的重構,因此可以從中吸取一些思路。對於代碼重構,有一個很重要的指導思想就是不要大規模進行重構,而是一小步一小步來。作為開發人員,每次聽到重寫代碼可能會很興奮,但實際上卻是充滿了風險,道路也是非常崎嶇坎坷,最終也有可能會失敗,每一個重寫過代碼的開發者可能對這一點深有體會。因此,與大規模進行重構相反,在進行微服務架構遷移時可以使用Martin Fowler提出絞殺(Strangler)模式。該策略名字來源於雨林中的絞殺藤,絞殺藤為了能夠爬到森林頂端都要纏繞著某棵大樹生長,最終使被纏繞的大樹死掉,只留下樹形一樣的絞殺藤。通過這種策略,我們在遷移時應首先圍繞著傳統應用開發出新的微服務應用,並逐漸替代傳統應用中的部分業務功能。通過這種方式逐步構建微服務應用,並替代、兼容整合舊的傳統應用,直到微服務承擔全部應用功能,而傳統單體架構應用此時也就可以退出歷史舞臺了。




之前,給大家發過三份Java面試寶典,這次新增了一份,目前總共是四份面試寶典,相信在跳槽前一個月按照面試寶典準備準備,基本沒大問題。

分別適用於初中級,中高級資深級工程師的面試複習。

內容包含java基礎、javaweb、mysql性能優化、JVM、鎖、百萬並發、消息隊列,高性能緩存、反射、Spring全家桶原理、微服務、Zookeeper、數據結構、限流熔斷降級等等。

獲取方式:點「在看」,V信關註上述Java最全面試題庫號並回復 【面試】即可領取,更多精彩陸續奉上。

相關焦點

  • 微服務架構設計
    (設計系統的組織,其產生的設計和架構等價於組織間的溝通結構。)Monolithic架構微服務也指一種種鬆耦合的、有一定的有界上下文的面向服務架構。也就是說,如果每個服務都要同時修改,那麼它們就不是微服務,因為它們緊耦合在一起;如果你需要掌握一個服務太多的上下文場景使用條件,那麼它就是一個有上下文邊界的服務,這個定義來自DDD領域驅動設計。
  • 微服務架構-設計總結
    八、微服務的優點和缺點九、思考:意識的轉變十、參考資料和推薦閱讀一、微服務架構介紹微服務架構(Microservice Architecture)是一種架構概念,旨在通過將功能分解到各個離散的服務中以實現對解決方案的解耦
  • 微服務架構設計(一):核心概念&從既有的架構遷移到微服務的策略
    摘要:微服務設計不應是一個講求標準答案, 簡單粗暴的設計過程。而應該是一個考量各方因素下的一個決策的過程。
  • 全面解析Netflix的微服務架構設計
    Netflix 意識到,它需要一個沒有單點故障的更可靠的基礎架構。因此它做出兩個重要決定:將 IT 基礎架構從自己的數據中心遷移到公共雲上,並通過微服務架構,用較小的易管理軟體組件替換單體程序。這兩個決定為今天 Netflix 的成功打下了堅實基礎。
  • 全面解析 Netflix 的微服務架構設計
    Netflix 意識到,它需要一個沒有單點故障的更可靠的基礎架構。因此它做出兩個重要決定:將 IT 基礎架構從自己的數據中心遷移到公共雲上,並通過微服務架構,用較小的易管理軟體組件替換單體程序。這兩個決定為今天 Netflix 的成功打下了堅實基礎。
  • 【雲計算】微服務架構設計 (一): 核心概念 & 從既有的架構遷移到微服務的策略
    微服務設計是架構設計。所以, 微服務設計不應是一個講求標準答案, 簡單粗暴的設計過程。
  • 微服務架構及其最重要的10個設計模式
    微服務架構的十個設計模式分別是獨享資料庫、事件驅動、CQRS、Saga、BFF、API 網關、Strangler、斷路器、外部化配置、消費端驅動的契約測試。從軟體開發早期(1960 年代)開始,應對大型軟體系統中的複雜性一直是一項令人生畏的任務。
  • 10個微服務架構設計的最佳實踐
    微服務極大改變了服務端引擎的架構方式。微服務不是一個單一的巨型的用來託管應用程式所有業務邏輯的代碼庫,而是反映了分布式系統模型,在該模型中,一組應用程式組件協同工作來滿足業務需求。通過遵循十項基本的微服務最佳實踐,你可以實現一個高效的微服務生態系統,從而避免不必要的架構複雜性。
  • 微服務架構及其最重要的 10 個設計模式
    設計模式讓我們可以分享通用詞彙並使用經實戰檢驗的方案,以免重複造輪子。現在,我將介紹一系列設計模式來實現這些最佳實踐。微服務架構的設計模式獨享資料庫(Database per Microservice)當一家公司將大型單體系統替換成一組微服務,首先要面臨的最重要決策是關於資料庫。單體架構會使用大型中央資料庫。即使轉移到微服務架構許多架構師仍傾向於保持資料庫不變。
  • Medium 的微服務架構
    我們已經建立了幾個附屬服務,但我們還沒有制定採用微服架構系統的戰略。隨著系統變得更加複雜和團隊的壯大,我們在 2018年初遷移到了微服務架構。在這篇文章中,我們希望分享我們的經驗,有效地做到這一點,避免微服務症候群。微服務架構是什麼?
  • 組件化、模塊化、集中式、分布式、服務化、面向服務的架構、微服務架構
    並不是所有的SOA架構都需要ESB,ESB是SCA特有的。當然任何符合ESB特徵的解決方式都可以稱之為ESB,也不僅僅是SCA內部的。因此,我們可以認為Echo並不太符合SOA的基本設計原則。而理想的SO接口和web界面一樣,也是變成系統入口和邊界,可能要對全世界開發者開放,因此SO在設計開發之中與OO相比其實會有很多不同。(微觀SOA:服務設計原則及其實踐方式(上篇))微服務架構微服務架構(MicroService)是一種服務化架構風格,通過將功能分散到各個離散的服務中以實現對解決方案的解耦。
  • 微服務下的數據架構
    ,對微服務的討論大多集中在容器或其他技術是否能很好的實施微服務,而本文將從以下幾個角度來和大家分享在微服務架構下進行數據設計需要關注的地方,旨在幫助大家在構建微服務架構時,提供一個從數據方面的視角:微服務定義微服務的優勢及架構特點微服務架構下的數據設計選擇一個合適的資料庫按照 Martin Fowler 的定義,微服務是一個軟體架構模式
  • DDD到底適不適合微服務架構?
    從初期的單體架構,到豎井式架構、RPC架構,再到大放異彩的微服務架構,可以說架構演進,本質上就是基於業務,對現有架構的抽象過程。一名架構師,最怕缺少全局意識和長線思維。如果架構師設計架構的出發點,只是緩解燃眉之急,那麼在未來,這套系統的迭代會越來越困難,很可能陷入推翻、重建,再推翻、再重建的「鬼打牆」。
  • Medium的微服務架構解析
    何為微服務架構首先,我們來思考微服務之架構是什麼,不是什麼。微服務是拯救那些過載和混亂軟體工程的技術趨勢之一。在Medium團隊,我們認為它是:「在微服務架構中,多個鬆散耦合的服務協同工作。微服務設計(建模)三原則以下介紹微服務建模時,我們都應該遵守這三個設計原則。這是實現微服務架構全部潛力的唯一途徑,錯失任何一個都會成為反模式。如果不是單一的目標,每個微服務慢慢就會做越來越多的事情,成長為多個「單片」服務。
  • 大牛帶你實時解讀微服務架構改造案例:天氣預報系統的架構設計
    天氣預報系統的架構設計到目前為止,天氣預報系統已經初具規模了。
  • 微服務架構雲端應用
    擁有超過12年網際網路產品開發和管理經驗,專注於網際網路技術架構設計,對產品設計、敏捷開發、安全、OKRs、大數據等領域有深入研究。現推崇反應式編程(http://www.reactivemanifesto.org/),並在多個產品中成功應用。劉總在這次分享中主要為大家介紹了什麼是徽服務,實現微服務有哪些架構模式以及微服務在實際中的應用情況。
  • 微服務架構體系
    定位Dubbo 是 SOA 時代的產物,關注點主要在於服務的調用,流量分發、流量監控和熔斷,定位服務治理和** RPC;Spring Cloud 誕生於微服務架構時代,考慮的是微服務治理的方方面面,另外由於依託Spirng
  • 流量洪峰中如何設計彈性微服務架構
    ,10多年的技術團隊管理經驗當技術架構轉型到微服務架構時,隨著業務流量增加,如何保障服務的高可用,如何針對服務進行有效的治理?我是在2013年開始做社交APP從原來單體改到微服務體系。在2014年到2015年的時候已經大規模上了go的微服務,整個場景切入到go。在今年8月7日,我把這麼多年沉澱的go微服務體系整理開源出來。本文給大家講一下,當切入到go微服務體系上,在流量洪峰突然到來的時候怎樣保證服務的穩定?
  • 微服務架構-從理想到現實
    單體應用規模太大,導致複雜度劇增,難以開發和管理單體應用開發,交付和變更周期變長,敏捷性跟不上單體應用本身在性能,擴展性上出現了問題在軟體架構設計裡面,分而治之始終都是解決複雜性的一個關鍵思維方法。包括在傳統軟體架構設計裡面對於大系統會進行子系統或組件劃分,會進行接口設計,集成設計等。
  • 雲上奈飛(二):Netflix全球視頻流服務的微服務架構設計
    Netflix 意識到,它需要一個沒有單點故障的更可靠的基礎架構。因此它做出兩個重要決定:將 IT 基礎架構從自己的數據中心遷移到公共雲上,並通過微服務架構,用較小的易管理軟體組件替換單體程序。這兩個決定為今天 Netflix 的成功打下了堅實基礎。