Java微服務分布式架構


摘自《Java微服務分布式架構企業實戰》

1.傳統單體應用架構存在的問題
  一個完整的單體應用程序通常主要由三部分組成:客戶端用戶界面、模塊和數據庫,如圖1.1所示。傳統單體應用的開發通常是創建一個由幾個業務模塊組成的項目,然后將項目打成一個包,部署在服務器上。

  項目的早期階段,這種方式很容易開發,部署也很方便。但是,隨着用戶需求的增加、項目功能的擴展,之前的小應用變得越來越臃腫、越來越復雜,這樣項目在開發和維護的過程中就會變得非常困難。一旦項目中出現了Bug,程序員在修改的過程中,會時刻處在“牽一發而動全身”的窘境之中。在單體應用中,每個服務的更新或改變都會導致重新部署整個應用,可維護性、靈活性逐漸降低,維護成本越來越高,效率越來越低。因此,隨着業務需求的發展,傳統的單體應用很難滿足互聯網時代不斷變化的需求。

 2.分布式系統開發的復雜性

  分布式系統的重要特性就是面向服務,它把整個系統拆分成不同的服務,然后將這些服務放在不同的服務器上、減少單體服務器的壓力,提高並發量和性能。它是由一系列計算機服務器組成的,由於用戶並不知道它背后的邏輯,所以感覺就像在訪問單個計算機一樣。分布式系統雖然在性能上表現很好,但是也帶來了系統的復雜性,例如分布式事務、分布式鎖、分布式Session、數據一致性等都是現在分布式系統中需要解決的難題。分布式系統設計遵循CAP定理、CAP是Consistency(一致性)、Availability(可用性)和Partition tolerance(分區容錯性)的簡稱。CAP定理認為,CAP的三種特性中,只能同時滿足其中兩種特性。1. 5節將詳細講解CAP定理。分布式系統如圖1. 2所示。

3.傳統架構與微服務架構的區別

  傳統架構與微服務架構在開發、部署方面都有很大的差別,接下來將通過對比兩者的缺點,及適用場景幫助更直觀地發現傳統架構與微服務架構的區別。

  1.傳統架構

  1)優點

    (1)結構簡單,容易理解。

    (2)請求響應快速。

    (3)部署簡單,所有功能一次打包。

  2)缺點

    (1)模塊之間的耦合度太高,其中一個模塊升級其他模塊都得升級。

    (2)開發困難,開發人員可能需要排隊等待。

    (3)系統的擴展性差。

    (4)不能靈活地進行分布式部署。適用場景:傳統架構更適用於對請求響應時間要求較高的應用、簡單的小型應用程序以及初創型企業資源緊張的初期項目,能夠節省資源,減少成本。

  2.微服務架構

  1)優點

    (1)項目被拆分,降低了耦合度,服務自治。

    (2)項目被拆分成若干個子項目,不同的團隊負責不同的子項目,提高了開發效率。

    (3)技術多樣性,可以根據業務上下文選擇合適的語言、工具進行構建,每個服務可以使用不同的技術,服務之間互相獨立。

    (4)易於擴展。增加功能時再增加一個子項目,調用其他系統的接口即可。

    (5)服務間采用輕量級通信機制相互溝通(通常是基於HTTP的Restful API).

    (6)可以靈活地進行分布式部署。

  2)缺點

    (1)系統之間交互需要使用遠程通信,接口開發會增加工作量。

    (2)HTTP請求速度慢,通常一個操作可能涉及多個微服務的相互調用,如果為了完成一個操作而多次從服務端調用不同的微服務,HTTP請求的耗時可能會成為瓶頸。

    (3)測試工作更加困難,部署更加復雜。

    (4)微服務應用是分布式系統,由此會帶來固有的復雜性。適用場景:適用於業務功能需求大、項目版本更新迭代快的大型分布式項目的開發。

 4.互聯網架構的演變

  隨着互聯網的發展,應用程序的用戶越來越多,產生的數據量也越來越大,隨之而來的一系列並發問題和存儲問題,使傳統的架構很難滿足開發的需要。因此,互聯網架構也逐步發展成為多種形態滿足不同的開發需求。目前比較主流的架構都是時代進化的產物,由簡單的單體架構到水平分層架構、SOA架構,最后再到微服務架構的開發,這些架構都是順應時代而生的,也承擔着不同的使命。沒有最好的架構,只有最合適的架構,在選擇一種架構開發應用程序之前就應當仔細了解該架構與要開發程序的應用場景是否匹配。接下來分別講解這幾種架構的特點。

  1)單體架構

  在應用程序開發完成后,打一個歸檔包(例如war格式),其中包含了該應用中的所有功能。單體應用結構簡單、容易理解,可以方便快速地打包部署到Jetty或者Tomcat 容器中,一次部署完成即可運行整個應用程序,還可以通過運行多個副本和結合負載均衡器擴展應用。單體架構如圖1. 4所示。

  從圖1. 4可以看出,單體架構是一個整體,所有業務邏輯、數據管理都在一起進行,模塊的邊界模糊,每修改一處代碼就可能會面臨很多問題的出現,代碼開發的效率低、擴展性差。

  2)水平分層架構

  在單體架構的基礎上,水平方向上將應用進行拆分為網關層、業務邏輯層、數據訪問層,每一層都是一個獨立的進程。常見的MVC模式的開發就是三層結構:模型(Model)、視圖(View)和控制器(Controller).每個層都各司其職,模型(Model)是應用程序中用於處理應用程序數據邏輯的部分,通常負責應用程序的持久化操作;視圖(View)是應用程序中處理數據顯示的部分;控制器(Controller)是應用程序中處理用戶交互的部分。MVC將不同職責划分到獨立的層次,各個層的依賴關系比較靈活,降低了單體架構中的耦合性,應用程序業務擴展較單體架構更為方便。每一層都可以根據業務需求進行獨立部署,如圖1. 5所示。

圖1. 5可以看出,一個應用程序被拆分為網關層、業務邏輯層、數據訪問層。分層架構設計最核心的一點就是需要保證各層之間的差異足夠清晰,邊界足夠明顯,並且分層架構能較好地支撐系統擴展性。例如網關層只需要處理PC端的邏輯,業務邏輯層只需要處理相關的業務邏輯,這樣在擴展某層的時候,其他層不受影響。

  3)SOA架構SOA架構是面向服務的架構。它是在單體架構的基礎上按照業務功能進一步垂直拆分的,SOA的組件之間是松耦合的,每一個服務都包含了自己的業務邏輯和多個適配器。把模塊拆分,使用接口通信,降低了模塊之間的耦合度,把項目拆分成若干個子項目,不同的團隊負責不同的子項目,使開發效率得到了提升,增加功能時只需要再增加一個子項目,然后調用其他系統的接口就可以實現,還可以靈活地進行分布式部署。SOA架構通常以獨立的形式存在於操作系統進程中,各個服務之間通過網絡通信,如圖1. 6所示。

  圖1. 6按照業務功能將項目進行了拆分,每個服務都是一個獨立的單體,它們之間通過企業服務總線進行交互,每個服務也可以被其他服務調用,在水平方向上並沒有進行拆分。因此,SOA的拆分也不夠徹底,是粗粒度、松耦合、無狀態的服務。

  4)微服務架構微服務架構的出現解決了SOA架構拆分不徹底的問題。微服務首先根據不同的業務功能進行垂直拆分,然后對垂直拆分后的服務,在水平方向繼續進行拆分。一個單體項目被划分為一個個網格的樣式,它解決了復雜問題,把可能會變得龐大的單體應用程序分解成一套服務。雖然功能數量不變,但是應用程序已經被分解成可管理的塊或者服務,每個服務都有一個明確的邊界。使用微服務架構模式,個體服務能夠被更快地開發,提高了開發效率,並且更容易理解與維護。微服務架構模式還可以實現每個微服務的獨立部署,不需要依賴其他微服務及其相關資源,如數據庫、內存緩存系統等。例如,前端如果想更改頁面樣式或者變更實現的技術語言,在完成開發后,重新部署與該改動相關的服務即可,並不需要重新部署整個項目,微服務架構模式使得持續部署成為可能。微服務架構如圖1. 7所示。

 5.微服務架構常見的設計模式

  1 聚合器微服務設計模式
  聚合器微服務設計模式如圖1. 8所示。

  由圖1. 8可知,該模式通過負載均衡使用聚合器調用多個服務,其中每個服務都有自己的緩存服務器和數據庫。所有的服務的接口都會暴露出來,最終由聚合器把所有檢索到的數據進行處理和展示,也可以把檢索到的數據增加業務邏輯形成新的微服務。這也是一種最常見也最簡單的設計模式。

  2 代理微服務設計模式
  代理微服務設計模式如圖1. 9所示。該模式是由聚合模式變化而來,這種模式在客戶端不會聚合數據,但是會根據業務需求的差別來調用不同的微服務。代理可以委派請求,也可以進行數據轉換工作。每個微服務都有自己獨立的緩存和數據庫系統,彼此獨立。

  3 鏈式微服務設計模式
  鏈式微服務設計模式如圖1. 10所示。由圖1. 10可知,當服務A接收到消息后會與服務B進行通信,然后服務B和服務C進行通信。由於是鏈式的,因此服務之間的消息是同步傳遞的,客戶端發出請求后,在沒收到響應的這段時間內一直是處於阻塞的,直到整個鏈條全部走完,響應給客戶端。因此,在使用鏈式微服務設計模式時應該特別注意服務鏈不應該太長,以免導致客戶端的長時間等待。

 

  4.分支微服務設計模式

  分支微服務設計模式如圖1.11所示。

  由圖1. 11可以看出,分支微服務設計模式更像是聚合器微服務設計模式和鏈式微服務設計模式的結合體。可以同時調用兩個服務鏈,當客戶端發送請求調用服務A時,服務A需要調用服務B同時也需要調用服務C,而服務C需要調用服務D.因此,就形成了分支微服務模式。

  5.數據共享微服務設計模式
  數據共享微服務設計模式如圖1. 12所示。

  在使用了微服務架構以后,數據庫不再設置外鍵,此時,就開始違反三大范式,即SQL數據庫反規范。所以數據就會出現冗余或重復,這是不可避免的。因此,在拆分重構階段的時候可以采取如圖1. 12所示的設計模式。
  6.異步消息傳遞微服務設計模式異步消息傳遞微服務設計模式如圖1. 13所示。

   由圖1. 13可以看出,服務A請求服務C時,服務C需要請求服務B,服務B也需要請求服務D,此時,雖然REST請求非常流行,但是同步會導致阻塞,因此,部分基於微服務的架構會采用消息隊列來替代REST的請求/響應。在圖1. 13中服務C是生產者,服務B是消費者,服務C只負責生產,消息隊列則負責持久化服務C生產的消息,隊列會幫助緩存消息,直到消費服務開始工作。

 6.CAP原則

1 CAP的定義

  CAP原則又被稱為CAP定理,它是指在一個分布式系統中,Consistency(一致性)、Availability(可用性)和Partition Tolerance(分區容錯性)三者在實際開發的過程中並不能同時兼顧,如圖1. 14所示。

  圖1. 14中的Consistency(一致性)指的是用戶在執行完(一致性)更新操作成功並返回客戶端后,所有節點在同一時間能夠查詢到的數據會保持完全一致,這就是分布式的一致性。例如,在A、B節點下現有某條數據記錄值為M,用戶向A發起一個寫操作,將M更改為N,接下來,用戶在執行讀操作時,取數據時就會得到N,這就叫一致性。用戶還有可能向B節點發起讀操作,由於B節點中的值沒有發生變化,因此返回的還是M,A節點和B節點讀操作的結果不一致,這就不滿足一致性了,如圖1. 15所示。

  為了讓M節點中的數據也能變為N,就要在向A節點執行寫操作的時候,讓A節點向B節點發送一條消息,要求B節點中的數據也改成N,如圖1. 16所示

  這樣,用戶向B節點發起讀操作,就也能得到N了。數據一致性的問題是分布式系統中需要正視的,對於客戶端來說,一致性指的是在進行並發訪問時已經更新過的數據如何才能夠准確地獲取到。從服務端來看,就是如何將更新能夠實時地同步到整個分布式系統中,確保數據最終的一致性。

  Availability(可用性)是指服務一直處於可用狀態,一旦接收到用戶的請求,服務器就必須給出回應,而且是正常響應時間。保持可用性主要就是為了使系統能夠反饋給用戶更好的體驗,不會出現如操作失敗、訪問鏈接超時等情況。

   Partition Tolerance(分區容錯性)指的是單台服務器或多台服務器出現問題后,其他正常服務的服務器依然可以正常的提供服務。在分布式系統中如果遇到某些節點或網絡分區故障的時候,仍然能夠繼續對外提供滿足一致性和可用性的服務。大多數分布式系統都會存在多個子網絡,而每個子網絡都可以稱為一個區(Partition).如B圖1. 7所示,A節點和B節點分別存在於兩台跨區的服務器上。A節M點向B節點發送一條消息,B節點可能無法收到該消息,這種情況是系統設計時必須要考慮到的。

  一般來說分區容錯是不可避免的,所以在CAP中情況中通常認為認P總是成立的。由於CAP定理可知,CAP三者之間不能同時兼顧,因此剩下的C和A必定無法同時做到。

  雖然面對的應用是一個分布式系統,但是分區容錯性要求整個系統在運行時更像是一個運轉正常的整體,當一個分布式系統中的一個機器宕機后,剩下的機器還能夠通過運轉滿足系統的需求,從而讓用戶在體驗上感覺並未受到影響。

2 CAP定理的證明

  接下來舉個簡單的小例子證明CAP不能夠同時滿足三個特性,並解釋其原因。假設現有兩台服務器,在其中的一台服務器中存放應用A和數據庫a,在另外一台服務器中存放應用B和數據庫b,保持這兩台服務器之間的連通性,模擬分布式系統的兩個子部分。在系統需要滿足Consistency(一致性)的情況下數據庫a和數據庫b中的數據是一樣的,此時無論用戶請求兩台服務器中的哪一台,都能夠取得同樣的響應數據結果,如果兩台服務器中任意一台機器宕機或網絡原因導致不可用,也不會影響正常的運作。
  當用戶在應用A上發起向數據庫更改的請求后,數據庫a的數據將被更改,此時,用過分布式系統的同步更新的操作也會把數據庫b中的數據進行更新,那么當用戶再通過應用B向數據庫發起查詢請求時,得到的響應結果也必然是更新后的數據。
  當然,這種情況是理想狀況下的正常運作,但是微服務系統開發免不了考慮網絡傳輸過程中所發生的一切不可預測的因素。也就是說,當兩台服務器之間的通信網絡在不可用的情況下該如何處理,此時還能否同時滿足一致性和可用性原則。
  面對以上問題,可以想象到當兩台服務器之間的通信斷開后,如果用戶向應用A發送更新請求,緊接着數據庫a中的數據固然是改變了,但是數據庫b中的數據還是之前的數據,倘若再有用戶訪問應用B並向數據庫發起讀操作,那么如果立即響應返回,得到的必然不是准確的數據。這時候就會面臨兩種選擇:要么犧牲數據一致性,立刻返回更新前的數據庫b中的數據;要么犧牲可用性,形成阻塞等待,直至網絡恢復連接,等待數據庫b中的數據更新完成后再響應給用戶。
  通過以上例子可以看出,在滿足容錯性的情況下,一致性和可用性只能取其一,即分布式系統不能夠同時滿足CAP特性。因此,就需要在搭建系統時考慮如何進行取舍。

3.取舍策略

  因為分布式系統中CAP三特性只能同時滿足其中兩個特性,因此,取舍策略就會有三種:CA/CP/AP

  如果選擇CA策略,就是希望能夠使系統同事滿足一致性和可用性,這就意味着放棄了分區容錯性。在分布式系統中放棄P就不能夠部署子節點,放棄了系統的可擴展性,這種做法顯然已經違背了分布式系統設計的初衷,不能分區的系統也不能稱為分布式系如果選擇CP策略,就是希望能夠使系統同時滿足一致性和分區容錯性,這就意味着所統了。要的數據更新操作都必須在同步完成后才能響應返回結果,這就需要在網絡發生故障或服務宕機時犧牲可用性,從而影響用戶的體驗。  

  如果選擇AP策略,就是希望能夠使系統同時滿足可用性和分區容錯性,放棄一致性。這樣一來每個節點中的數據只能為本地應用提供服務,導致全局不一致性。典型的例子就是當雙11在網上搶購商品時,有時候打開購物頁面發現還有商品庫存,但是當你立刻搶購時卻發現反饋提示商品已經售空,這就是因為在可用性的前提下,犧牲了數據一致性。這樣雖然或多或少會影響一些用戶的體驗,但不會造成嚴重阻塞。

4 CAP總結

  當今大多數的大型互聯網應用都是以集群部署的,主機很多,部署也相對分散,隨着業務的發展,節點也會變得越來越多,因此,節點的故障和網絡不可測導致故障都將會是分布式系統面臨的常態問題,所以大多數的應用也就只能在C和P中做取舍。還有一部分例如銀行等傳統行業,涉及的金錢數據是必須要保證數據一致性的,不能有絲毫偏差,因此,在搭建這種項目之前,首先考慮的是滿足一致性,如果出現網絡故障,寧可停止繼續提供服務,也不能讓臟數據產生。總而言之,策略沒有好壞之分,一個好的系統是根據業務場景進行架構設計的,只有最合適的策略才是最好策略。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM