1.1系統架構的演變 隨著互聯網的發展,網站應用的規模不斷擴大,常規的應用架構已無法應對,分散式服務架構以及微服務架構勢在必行,亟需一個治理系統確保架構有條不紊的演進。 1.1.1單體應用架構 Web應用程式發展的早期,大部分web工程(包含前端頁面,web層代碼,service層代碼,dao層代碼 ...
隨著互聯網的發展,網站應用的規模不斷擴大,常規的應用架構已無法應對,分散式服務架構以及微服務架構勢在必行,亟需一個治理系統確保架構有條不紊的演進。
1.1.1單體應用架構
Web應用程式發展的早期,大部分web工程(包含前端頁面,web層代碼,service層代碼,dao層代碼)是將所有的功能模塊,打包到一起並放在一個web容器中運行。
比如搭建一個電商系統:客戶下訂單,商品展示,用戶管理。這種將所有功能都部署在一個web容器中運行的系統就叫做單體架構。
優點:
-
系統的簡易性:系統語言風格、業務結構,介面格式均具有一致性,服務都是耦合在一起的,不存在各個業務通信問題。
-
易於測試:單體應用一旦部署,所有的服務或特性就都可以使用了,簡化了測試過程,無需額外測試服務間的依賴,測試均可在部署完成後開始。
-
易於部署與升級:相對於微服務架構中的每個服務獨立部署,單體系統只需將單個目錄下的服務程式統一部署和升級。
-
較低的維護成本:只需維護單個系統即可。運維主要包括配置、部署、監控與告警和日誌收集四大方面。相對於單體系統,微服務架構中的每個服務都需要獨立地配置、部署、監控和日誌收集,成本呈指數級增長。
缺點:
-
複雜性高:由於是一個單體的系統,所以整個系統的模塊是耦合在一起的,模塊的邊界比較模糊、依賴關係錯綜複雜。功能的調整,容易帶來不可知的影響和潛在的bug風險。
-
服務性能問題:單體系統遇到性能瓶頸問題,只能橫向擴展,增加服務實例,進行負載均衡分擔壓力。無法縱向擴展,做模塊拆分。
-
擴縮容能力受限:單體應用只能作為一個整體進行擴展,影響範圍大,無法根據業務模塊的需要進行單個模塊的伸縮。
-
無法做故障隔離:當所有的業務功能模塊都聚集在一個程式集當中,如果其中的某一個小的功能模塊出現問題(如某個請求堵塞),那麼都有可能會造成整個系統的崩潰。
-
發佈的影響範圍較大:每次發佈都是整個系統進行發佈,發佈會導致整個系統的重啟,對於大型的綜合系統挑戰比較大,如果將各個模塊拆分,哪個部分做了修改,只發佈哪個部分所在的模塊即可。
1.1.2垂直應用架構
當訪問量逐漸增大,單一應用增加機器帶來的加速度越來越小,將應用拆成互不相干的幾個應用,以提升效率
優點:
-
項目架構簡單,前期開發成本低,周期短,小型項目的首選。
-
通過垂直拆分,原來的單體項目不至於無限擴大
-
不同的項目可採用不同的技術。
缺點:
-
全部功能集成在一個工程中,對於大型項目不易開發、擴展及維護。
-
系統性能擴展只能通過擴展集群結點,成本高、有瓶頸。
1.1.3 分散式SOA架構
1.1.3.1 什麼是SOA
SOA 全稱為 Service-Oriented Architecture,即面向服務的架構。它可以根據需求通過網路對鬆散耦合的粗粒度應用組件(服務)進行分散式部署、組合和使用。一個服務通常以獨立的形式存在於操作系統進程中。
站在功能的角度,把業務邏輯抽象成可復用、可組裝的服務,通過服務的編排實現業務的快速再生,目的:把原先固有的業務功能轉變為通用的業務服務,實現業務邏輯的快速復用。通過上面的描述可以發現 SOA 有如下幾個特點:分散式、可重用、擴展靈活、松耦合
1.1.3.2 SOA 架構
當垂直應用越來越多,應用之間交互不可避免,將核心業務抽取出來,作為獨立的服務,逐漸形成穩定的服務中心,使前端應用能更快速的響應多變的市場需求
優點:
-
抽取公共的功能為服務,提高開發效率
-
對不同的服務進行集群化部署解決系統壓力
-
基於ESB/DUBBO減少系統耦合
缺點:
-
抽取服務的粒度較大
-
服務提供方與調用方介面耦合度較高
1.1.4 微服務架構
微服務:將原本大塊的服務細化,變成粒度更小的服務。 使其耦合度更底,重用性更高。將服務拆分出去,也是為了降低單個服務的壓力,避免服務經常因為負載過高而崩潰的問題。
優點:
-
通過服務的原子化拆分,以及微服務的獨立打包、部署和升級,小團隊的交付周期將縮短,運維成 本也將大幅度下降
-
微服務遵循單一原則。微服務之間採用Restful等輕量協議傳輸。
缺點:
-
微服務過多,開發成本高
-
服務拆分如果不當,反而會適得其反
-
分散式系統開發的技術成本高(容錯、分散式事務等)
1.1.5 SOA與微服務的關係
SOA( Service Oriented Architecture )“面向服務的架構”:他是一種設計方法,其中包含多個服 務, 服務之間通過相互依賴最終提供一系列的功能。一個服務 通常以獨立的形式存在與操作系統進程 中。各個服務之間 通過網路調用。
微服務架構: 其實和 SOA 架構類似,微服務是在 SOA 上做的升華,微服務架構強調的一個重點是“業務需 要徹底的組件化和服務化”,原有的單個業務系統會拆分為多個可以獨立開發、設計、運行的小應用。 這些小應用之間通過服務完成交互和集成。
功能 | SOA | 微服務 |
---|---|---|
組件大小 | 大塊業務邏輯 | 單獨任務或小塊業務邏輯 |
耦合 | 通常松耦合 | 總是松耦合 |
公司架構 | 任何類型 | 專註於功能交叉團隊 |
管理 | 著重中央管理 | 著重分散管理 |
目標 | 確保應用能夠交互操作 | 執行新功能、快速拓展開發團隊 |
1.2 分散式核心知識
1.2.1 分散式中的遠程調用
在微服務架構中,通常存在多個服務之間的遠程調用的需求。遠程調用通常包含兩個部分:序列化和通 信協議。常見的序列化協議包括json、xml、hession、protobuf、thrift、text、bytes等,目前主流的 遠程調用技術有基於HTTP的RESTful介面以及基於TCP的RPC協議。
(1) RESTful 介面
REST,即Representational State Transfer(表現層狀態轉換)的縮寫,如果一個架構符合REST原則,就稱它為RESTful架 構。
資源(Resources)
所謂"資源",就是網路上的一個實體,或者說是網路上的一個具體信息。它可以是一段文本、一張圖 片、一首歌曲、一種服務,總之就是一個具體的實在。你可以用一個URI(統一資源定位符)指向它, 每種資源對應一個特定的URI。要獲取這個資源,訪問它的URI就可以,因此URI就成了每一個資源的地 址或獨一無二的識別符。REST的名稱"表現層狀態轉化"中,省略了主語。"表現層"其實指的是"資 源"(Resources)的"表現層"。
表現層(Representation)
"資源"是一種信息實體,它可以有多種外在表現形式。我們把"資源"具體呈現出來的形式,叫做它的"表 現層"(Representation)。比如,文本可以用txt格式表現,也可以用HTML格式、XML格式、JSON格 式表現,甚至可以採用二進位格式;圖片可以用JPG格式表現,也可以用PNG格式表現。URI只代表資源 的實體,不代表它的形式。嚴格地說,有些網址最後的".html"尾碼名是不必要的,因為這個尾碼名錶示 格式,屬於"表現層"範疇,而URI應該只代表"資源"的位置。
狀態轉化(State Transfer)
訪問一個網站,就代表了客戶端和伺服器的一個互動過程。在這個過程中,勢必涉及到數據和狀態的變 化。互聯網通信協議HTTP協議,是一個無狀態協議。這意味著,所有的狀態都保存在伺服器端。因 此,如果客戶端想要操作伺服器,必須通過某種手段,讓伺服器端發生"狀態轉化"(State Transfer)。 客戶端用到的手段,只能是HTTP協議。具體來說,就是HTTP協議裡面,四個表示操作方式的動詞: GET、POST、PUT、DELETE。它們分別對應四種基本操作:GET用來獲取資源,POST用來新建資源 (也可以用於更新資源),PUT用來更新資源,DELETE用來刪除資源。
綜合上面的解釋,我們總結一下什麼是RESTful架構:
-
每一個URI代表一種資源;
-
客戶端和伺服器之間,傳遞這種資源的某種表現層;
-
客戶端通過四個HTTP動詞,對伺服器端資源進行操作,實現"表現層狀態轉化"。
(2)RPC協議
什麼是RPC
RPC(Remote Procedure Call:遠程過程調用 ) 一種進程間通信方式。允許像調用本地服務一樣調用遠程服務。RPC 框架的主要目標就是讓遠程服務調用更簡單、透明。RPC框架負責屏蔽底層的傳輸方式(TCP或者 UDP)、序列化方式(XML/JSON/二進位)和通信細節。開發人員在使用的時候只需要瞭解誰在什麼 位置提供了什麼樣的遠程服務介面即可,並不需要關心底層通信細節和調用過程。
常見的RPC框架有:
-
OpenFeign
-
gRPC
Why Not HttpClient
可能你常聽到什麼什麼之間是 RPC 調用的,那你有沒有想過為什麼要 RPC, 我們直接 WebClient HTTP 調用不行麽?
其實 RPC 調用是因為服務的拆分,或者本身公司內部的多個服務之間的通信。
服務的拆分獨立部署,那服務間的調用就必然需要網路通信,用 WebClient 調用當然可行,但是比較麻煩。我們想即使服務被拆分了但是使用起來還是和之前本地調用一樣方便。
所以就出現了 RPC 框架,來屏蔽這些底層調用細節,使得我們編碼上還是和之前本地調用相差不多。
並且 HTTP 協議比較的冗餘,RPC 都是內部調用所以不需要太考慮通用性,只要公司內部保持格式統一即可。
所以可以做各種定製化的協議來使得通信更高效。
比如規定 yes 代表 yes的練級攻略,你看是不是更高效了,少傳輸的 5 個字。
就像特殊行動的暗號,高效簡潔!
[ApiController] public class CityController:ControllerBase { private readonly ProvinceClient _provinceClient; // rpc 介面 public CityController(ProvinceClient provinceClient){ _provinceClient=provinceClient; } //獲取所有省份 [HttpGet] public Result<List<ProvinceDto>> GetProvinces(){ return _provinceClient.GetAll(); } }
(3) 區別與聯繫
HTTP 和 RPC 其實是兩個維度的東西, HTTP 指的是通信協議。
而 RPC 則是遠程調用,其對應的是本地調用。
RPC 的通信可以用 HTTP 協議,也可以自定義協議,是不做約束的。
小結
-
公司內部服務的調用一般都用 RPC,而 HTTP 的優勢在於通用,大家都認可這個協議。
-
三方平臺提供的介面都是通過 HTTP 協議調用的。
1.3 CAP 理論
分散式系統(distributed system)正變得越來越重要,大型網站幾乎都是分散式的。
分散式系統的最大難點,就是各個節點的狀態如何保持一致。CAP理論是在設計分散式系統的過程中,處理數據一致性問題時必須考慮的理論。
一、什麼是CAP理論
CAP即:
-
Consistency(一致性)
-
Availability(可用性)
-
Partition tolerance(分區容忍性)
這三個性質對應了分散式系統的三個指標: 而CAP理論說的就是:一個分散式系統,不可能同時做到這三點。如下圖:
接下來將詳細介紹C A P 三個指標的含義,以及三者如何權衡。
二 、 C、 A、P的含義
借用一下維基百科
Consistency : Every read receives the most recent write or an error Availability : Every request receives a (non-error) response – without the guarantee that it contains the most recent write Partition tolerance : The system continues to operate despite an arbitrary number of messages being dropped (or delayed) by the network between nodes
翻譯一下就是: ①一致性:對於客戶端的每次讀操作,要麼讀到的是最新的數據,要麼讀取失敗。換句話說,一致性是站在分散式系統的角度,對訪問本系統的客戶端的一種承諾:要麼我給您返回一個錯誤,要麼我給你返回絕對一致的最新數據,不難看出,其強調的是數據正確。
②可用性:任何客戶端的請求都能得到響應數據,不會出現響應錯誤。換句話說,可用性是站在分散式系統的角度,對訪問本系統的客戶的另一種承諾:我一定會給您返回數據,不會給你返回錯誤,但不保證數據最新,強調的是不出錯。
③分區容忍性:由於分散式系統通過網路進行通信,網路是不可靠的。當任意數量的消息丟失或延遲到達時,系統仍會繼續提供服務,不會掛掉。換句話說,分區容忍性是站在分散式系統的角度,對訪問本系統的客戶端的再一種承諾:我會一直運行,不管我的內部出現何種數據同步問題,強調的是不掛掉。
三、權衡 C、A
之前提到,CAP理論說一個分散式系統不可能同時滿足C、A、P這三個特性。那麼我們就來分析C、A、P的權衡吧。
note:其實這裡有個關於CAP理論理解的誤區。不要以為在所有時候都只能選擇兩個特性。在不存在網路失敗的情況下(分散式系統正常運行時),C和A能夠同時保證。只有當網路發生分區或失敗時,才會在C和A之間做出選擇。
對於一個分散式系統而言,P是前提,必須保證,因為只要有網路交互就一定會有延遲和數據丟失,這種狀況我們必須接受,必須保證系統不能掛掉。所以只剩下C、A可以選擇。要麼保證數據一致性(保證數據絕對正確),要麼保證可用性(保證系統不出錯)。
當選擇了C(一致性)時,如果由於網路分區而無法保證特定信息是最新的,則系統將返回錯誤或超時。
當選擇了A(可用性)時,系統將始終處理客戶端的查詢並嘗試返回最新的可用的信息版本,即使由於網路分區而無法保證其是最新的。
四、C、A、P三者之間的衝突
本部分主要參考
假設有兩台伺服器,一臺放著應用A和資料庫V,一臺放著應用B和資料庫V,他們之間的網路可以互通,也就相當於分散式系統的兩個部分。
在滿足一致性的時候,兩台伺服器(假設為N1,N2)的數據是一樣的,DB0=DB0。在滿足可用性的時候,用戶不管是請求N1或者N2,都會得到立即響應。在滿足分區容錯性的情況下,N1和N2有任何一方宕機,或者網路不通的時候,都不會影響N1和N2彼此之間的正常運作。
圖1中,用戶通過N1中的A應用請求數據更新到伺服器DB0,這時N1中的伺服器DB0變為DB1,通過分散式系統的數據同步更新操作,N2伺服器中的資料庫V0也更新為了DB1(圖2),這時,用戶通過B向資料庫發起請求得到的數據就是即時更新後的數據DB1。
上面是正常運作的情況,但分散式系統中,最大的問題就是網路,現在假設一種極端情況,N1和N2之間的網路斷開了,但我們仍要支持這種網路異常,也就是滿足分區容錯性,那麼這樣能不能同時滿足一致性和可用性呢?
假設N1和N2之間通信的時候網路突然出現故障,有用戶向N1發送數據更新請求,那N1中的數據DB0將被更新為DB1,由於網路是斷開的,N2中的資料庫仍舊是DB0;
如果這個時候,有用戶向N2發送數據讀取請求,由於數據還沒有進行同步,應用程式沒辦法立即給用戶返回最新的數據DB1,怎麼辦呢?有二種選擇,第一,犧牲數據一致性,響應舊的數據DB0給用戶;第二,犧牲可用性,阻塞等待,直到網路連接恢復,數據更新操作完成之後,再給用戶響應最新的數據DB1
配套視頻鏈接:課程簡介 (cctalk.com)
海闊平魚躍,天高任我行,給我一片藍天,讓我自由翱翔。