本文要介紹的是 服務化架構(gòu) (Service-Based Architecture, SBA )。
SBA 可以看成是單體架構(gòu)和微服務架構(gòu)之間的一個折中方案,它也是按照業(yè)務領(lǐng)域進行服務劃分,但服務劃分的粒度相比微服務要更粗。SBA 與微服務架構(gòu)一大不同是, 它允許各個服務間共享同一個數(shù)據(jù)庫實例 ,這也使得 SBA 在架構(gòu)上既有單體架構(gòu)的特點,也有分布式架構(gòu)的特點,顯得更加的靈活。因此, 從單體架構(gòu)演進到 SBA,會比直接演進到微服務架構(gòu)更加容易 。
架構(gòu)視圖
基礎(chǔ)視圖
SBA 的基礎(chǔ)架構(gòu)視圖分成 3 部分:
- User Interface ,作為系統(tǒng)的接入口,接收客戶端的請求,并轉(zhuǎn)發(fā)到業(yè)務服務。。
- Domain Services ,業(yè)務服務按照領(lǐng)域進行劃分,分開部署、業(yè)務獨立。
- Database ,服務間共享的數(shù)據(jù)庫實例,因為數(shù)據(jù)庫實例只有一個,所以可以支持 ACID 事務。
使用 SBA 的系統(tǒng)通常只會劃分 4 ~ 12 個服務,避免產(chǎn)生過多的數(shù)據(jù)庫連接。服務數(shù)量不多,也決定了 SBA 中的服務相比微服務架構(gòu)中的服務有著更粗的粒度。User Interface 與服務間通過遠程通信協(xié)議來完成業(yè)務往來,常見的通信方式有REST、RPC、消息隊列等。需要注意的是, SBA 是不允許服務間通信的 ,這與微服務架構(gòu)有著本質(zhì)的區(qū)別。
大多數(shù)情況下, SBA 中的服務只有一個或者少量實例 ,與微服務動輒成百上千個實例有著很大的區(qū)別。主要是因為 SBA 服務粒度更粗,無法做到像微服務那樣精準的按需擴容,擴容太多反而會導致資源的浪費。
SBA 的另一大特點是允許所有服務共享同一數(shù)據(jù)庫實例 ,使得它能夠直接將傳統(tǒng)單體架構(gòu)的那一套 SQL 查詢邏輯、ACID 事務搬過來,讓架構(gòu)的演進更加的平滑。不過,共享數(shù)據(jù)也會帶來一些問題,比如數(shù)據(jù)模型變更的影響范圍更大,后面會在“ 數(shù)據(jù)拆分” 一節(jié)詳細講述。
拆分 User Interface
在大型系統(tǒng)中,單一的 User Interface 可能導致代碼耦合、性能瓶頸等問題,這時候我們可以進一步對它進行拆分。拆分的方法可以是 基于業(yè)務領(lǐng)域的拆分 ,業(yè)務相關(guān)的幾個服務使用同一個 User Interface;或者 基于服務的拆分 ,為每個服務都配備一個 User Interface。
拆分 Database
類似地,我們也可以對數(shù)據(jù)庫進行拆分,可以拆分成幾個服務共享一個實例;也可以像微服務架構(gòu)中那樣,每個服務獨享一個實例。數(shù)據(jù)庫拆分的原則就是: 確保數(shù)據(jù)是解耦的,不會被其他服務所依賴 ,避免出現(xiàn)跨庫查詢或服務間通信。
增加 API 網(wǎng)關(guān)
我們也可以在 User Interface 和 Domain Services 之間增加一個 API 網(wǎng)關(guān)層,提供流控、鑒權(quán)、指標統(tǒng)計、服務發(fā)現(xiàn)等公共能力,進一步提升系統(tǒng)架構(gòu)的安全性、可靠性、可維護性。
業(yè)務服務的設計
SBA 中的服務具有較粗的粒度,因此在業(yè)務服務的架構(gòu)設計上通常也會用到一些單體架構(gòu)模式,常見的有分層架構(gòu)和基于領(lǐng)域的 組件化架構(gòu) 。
不管是分層架構(gòu)還是組件化架構(gòu),通常都需要增加一個 API 層,負責編排和轉(zhuǎn)發(fā)來自 User Interface 的業(yè)務請求。下面以訂單創(chuàng)建流程作為示例。
假設現(xiàn)在有一個訂單服務 OrderService
,當它的 API 層接收到來自 User Interface 的訂單創(chuàng)建請求時,API 層協(xié)調(diào)會各個組件依次完成如下的幾個業(yè)務流程 :
- 調(diào)用訂單組件,完成訂單ID、訂單內(nèi)容的生成。
- 調(diào)用支付組件,完成用戶的扣款。
- 調(diào)用庫存組件,更新商品的庫存數(shù)量。
因為這些業(yè)務流程都是在同一個服務內(nèi)完成,當其中的某個流程異常后,我們很容易通過數(shù)據(jù)庫的 ACID 事務來完成回滾,從而能夠確保 數(shù)據(jù)的強一致性 。
相比在微服務架構(gòu)之下,訂單創(chuàng)建請求往往需要訂單微服務、支付微服務、庫存微服務之間協(xié)作來完成,這就涉及到分布式事務,也即 BASE(Basic Availability, Soft state, Eventual consistency) 事務。BASE 事務更加的復雜,而且無法保證數(shù)據(jù)的強一致性。
當然,更粗的服務粒度也會帶來 服務可用性問題 ,比如在訂單服務例子中,你會因為訂單ID生成邏輯的變更而升級整個服務,也會因為庫存組件中的一個BUG導致整個服務的故障。
所以,服務粒度的粗與細,實際上也是數(shù)據(jù)一致性和服務可用性的一次 trade-off 。
數(shù)據(jù)拆分
服務間共享數(shù)據(jù)庫使得系統(tǒng)具有更強的數(shù)據(jù)完整性和一致性,但簡單的單庫單表數(shù)據(jù)模型會帶來耦合的問題。
在單庫單表的模型下,我們大概率會這么實現(xiàn),將與數(shù)據(jù)庫操作相關(guān)的實體對象、SQL 邏輯全部封裝在一個共享的 shared lib 庫上,供所有業(yè)務服務復用:
這樣的實現(xiàn)方式雖然簡單,但是會帶來“ 牽一發(fā)而動全身 ”的問題。假設某個服務所用到的某個字段類型需要變化,勢必會修改表結(jié)構(gòu)和 shared lib 庫,而這兩者是所有服務共用的,因此也就會導致所有服務都需要升級重新上線。這樣的耦合會給 SRE 帶來極大的困擾,一點也不 敏捷 。
更好的方法是 根據(jù)業(yè)務對數(shù)據(jù)進行拆分 ,將相對獨立的數(shù)據(jù)拆分成多個表,每個表都有一個獨立的 lib 庫,對于公共表,則有一個 common lib 庫,各服務按需依賴。對于 common lib 庫的變更,我們還可以通過版本控制來盡量降低影響范圍,但必須在 common lib 進行版本升級時 保持向后兼容 。
SBA 雖然是分布式架構(gòu),但是也保留了單體架構(gòu)下的一些特點,在架構(gòu)上具有較高的靈活性,也使得它在各方面的評分都比較高,沒有明顯的缺點。
SBA 是一個 domain-partitioned 的架構(gòu),因此適合使用領(lǐng)域驅(qū)動設計來進行領(lǐng)域限界上下文的劃分,進而規(guī)劃出業(yè)務獨立的服務。服務間業(yè)務獨立,而且不會相互間通信,也就意味著具有更好的 Testability 。
前文有提到過,SBA 雖然支持服務實例擴容,但是更粗的服務粒度會導致擴容的性價比并不高,因此 Scalability 和 Elasticity 得分不高。
Scalability 和 Elasticity的差異:
- Scalability 通常指軟件系統(tǒng)在不中斷業(yè)務的前提下,通過 scale-up 或 scale-out 等手段來應對更高業(yè)務負載,強調(diào)的是軟件系統(tǒng)應對高負載的能力。
- Elasticity 通常指硬件系統(tǒng)能夠根據(jù)實際的業(yè)務負載情況,適時增加或減少硬件資源,強調(diào)的是硬件資源的高效利用。
總結(jié)
如果你打算從單體架構(gòu)演進到分布式架構(gòu),SBA 會是一個不錯的選擇 :
- 相比單體架構(gòu),SBA 按照業(yè)務進行服務拆分,在業(yè)務解耦、開發(fā)流程敏捷等方面有著明顯的優(yōu)勢。
- 相比其他分布式架構(gòu),SBA 有著更粗的服務粒度,因此也得以減少了服務間的遠程調(diào)用、網(wǎng)絡帶寬消耗,受網(wǎng)絡故障的影響更小。
- 服務間共享數(shù)據(jù)庫使得 SBA 支持 ACID 事務,在數(shù)據(jù)一致性方面具有良好的表現(xiàn),但我們還是應該盡量按照業(yè)務進行分表,避免出現(xiàn)嚴重的數(shù)據(jù)耦合。
- 在架構(gòu)評分上,SBA 各方面評分都不錯,沒有明顯的缺點,是典型的“ 六邊形戰(zhàn)士 ”。
-
架構(gòu)
+關(guān)注
關(guān)注
1文章
513瀏覽量
25468 -
微服務架構(gòu)
+關(guān)注
關(guān)注
0文章
25瀏覽量
2959
發(fā)布評論請先 登錄
相關(guān)推薦
評論