螞蟻SOFA系列(1) - 聊聊SOFA的模塊化

做者:404,轉載請註明出處。歡迎關注公衆號:404P。java

SOFA是螞蟻自研的一套金融級分佈式中間件,目前正在逐步向業界開源。SOFA的全稱有兩個,最先是Service Oriented Fabric Architecture,即面向服務的架構。隨着2018年的開源,其全稱改成Scalable Open Financial Architecture,便可擴展的開源金融架構。程序員

SOFA技術棧包含了微服務架構體系的各種組件,主要包括RPC框架,服務註冊中心,分佈式鏈路追蹤,Metrics監控度量等。web

本文咱們來聊聊SOFA的模塊化。spring

一 什麼是模塊化

模塊化在計算機領域是常常討論的話題,在學校學編程語言的時候,教科書上說程序設計要遵循模塊化原則。編程

模塊化程序設計是指在進行程序設計時將一個大程序按照功能劃分爲若干小程序模塊,每一個小程序模塊完成一個肯定的功能,並在這些模塊之間創建必要的聯繫,經過模塊的互相協做完成整個功能的程序設計方法。小程序

上面這段話引自百度百科,其實精煉下就是:高內聚和低耦合網絡

file

二 模塊化思想演變

1 代碼設計模塊化

最先學編程的時候,實現一個功能,全部邏輯放到一個main函數裏去,後來發現理不清了,就把main裏面的邏輯抽成幾個函數。這是模塊化嗎?是。這個模塊化是最基本的代碼設計能力,加強代碼的可讀性、可維護性和可擴展性。以下圖,計算成績的時候,沒有把全部邏輯放在A中,而是分在B1和B2中,單獨計算,最後A調用B一、B2來實現。架構

file

在這種簡單的程序設計中,每每更注重邏輯的內聚性,只要內聚作好了,每每就是低耦合的。框架

2 業務領域模塊化

在真實作一些項目的時候,業務系統比較複雜,要實現的功能不少。這個時候出現了橫向和縱向的模塊化設計。橫向的就是分層設計,縱向的就是按照不通的業務領域來設計。maven

一個業務系統,橫向的模塊化切分主要分爲三大層:Web層,Service層,DAL層。

在業務初期,功能每每都是寫在一個業務系統的,好比訂單模塊Order、庫存模塊Stock。在maven中這些模就是不一樣的module,但運行都是在同一個JVM,同一個web容器中的。

file

這在種狀況下,訂單服務依賴於庫存服務怎麼辦?訂單模塊的pom中引入庫存模塊的依賴。而後注入bean。

public class OrderService {
    @Autowired
    private StockService stockService;
}
複製代碼

這種橫縱模塊化思想隨着業務的複雜開始進化了。訂單、庫存模塊雖然在一個Service層,但屬於明顯不一樣的領域,已經被分紅不一樣的模塊了,具備很好的內聚性,並且要引用其它模塊,必須引入pom依賴以後才能訪問,具備不錯的隔離型。

3 業務系統模塊化的弊端

可是,這樣設計的耦合性仍是不夠低,隔離性不夠強。

程序員小胖:還不夠強嗎?訂單模塊和庫存模塊都在不一樣的module了,不費任何力氣,就能夠直接把源代碼分紅兩個項目,由不一樣的團隊來寫了。

404P: 不夠,如今的隔離性最多在開發層,可以相互隔離開發。運行時呢?

全部module的bean都在同一個spring context中,A模塊能夠任意引用B模塊的bean,開發同窗引入另外一個module以後,不太清楚該module中哪些是對外提供的的接口,哪些bean是能夠直接注入調用的,哪些Bean是內部Bean,不適合直接去注入的。

長期如此,一個模塊的bean被不斷地注入到另一個模塊被調用,那麼其運行時的隔離性就差了。運行時沒有作好隔離,是服務拆分的一大痛點。大概就是下圖這個樣子。

file

程序員小胖:請繼續你的表演。

404P:隨着業務的增加,必然會把Order和Stock拆分,成爲不一樣的子業務系統。代碼在不一樣的module,拆分開來很簡單,可是拆分後兩個業務系統是運行在不一樣的SpringContext中的。而bean的注入只在一個SpringContext有效,因此以前經過bean注入來實模塊交互的地方須要梳理出來,變成系統之間的接口交互才能實現服務拆分。

程序員小胖:聽你這麼一說,有道理。模塊化思想都是跟着架構思想走的啊。若是要考慮將來模塊拆分紅服務,就須要考慮好運行時隔離,也就是運行時的低耦合交互。

404P: 是的。看看SOFA怎麼作的。

三 SOFA模塊化

爲了防止這種模塊之間濫用bean注入來交互。SOFA啓動後,會爲每一個moudule建立一個SpringContext,每一個module運行在各自的SpringContext中。不一樣模塊之間的bean沒法直接引用,具有了較好的運行時隔離能力。

file

那麼當Order模塊想引用Stock模塊的Bean,怎麼辦呢?

首先,須要Stock模塊有發佈對外的公共bean,經過以下聲明式發佈(也能夠經過註解方式):

<sofa:service ref="stockBeanA" interface="com.alipay.sofa.StockBeanA"/>
複製代碼

那Order模塊怎麼引用Stock模塊中的公開bean呢?經過以下聲明方式引用:

<sofa:reference id="stockBeanA" interface="com.alipay.sofa.StockBeanA"/>
複製代碼

Stock模塊的stockBeanA已經公開發布,而且Order模塊已經引用,那麼Order模塊在編碼的時候,就能夠直接注入bean stockBeanA了。

這種方式,咱們能夠很清晰地看到一個模塊公開了哪些服務,引用了哪些服務。模塊之間的交互變得很是清晰。

四 SOFA模塊拆分紅微服務

當一個SOFA應用開始變得複雜,開發團隊成員開始增多時,就須要進行服務化了。好比,Order模塊和Stock模塊,再也不是運行在一個系統了,而是要變成Order系統和Stock系統了。這意味着這兩個領域之間的交互從模塊級別的交互上升到應用系統級別的交互了。

file

這種服務化拆分須要考慮兩點:

(1)模塊化的交互是在同一JVM內存中不一樣SpringContext之間的交互,拆分紅兩個應用系統後,應用系統之間交互必然是經過網絡請求來交互,必然要考慮遠程通訊的問題。

(2)模塊之間的服務發佈和引用與應用系統之間的服務發佈和引用是否有差別,須要改造?

SOFA考慮了以上兩點,要將一個SOFA模塊拆成微服務是很是便捷的。

Stock應用發佈的時候,以下:

<sofa:service ref="stockBeanA" interface="com.alipay.sofa.StockBeanA">
    <sofa:binding.bolt/>
</sofa:service>
複製代碼

Order應用引用Stock的服務時,以下

<sofa:reference id="stockBeanA" interface="com.alipay.sofa.StockBeanA">
    <sofa:binding.bolt/>
</sofa:reference>
複製代碼

能夠看出,就是添加了個屬性 ,

<sofa:binding.bolt/>
複製代碼

表示服務之間的交互是經過sofa bolt遠程調用框架來完成,發佈和引用方式幾乎沒有變化。這種簡易的服務化拆分,爲螞蟻架構在服務化演進的過程當中帶來了很大的便利。

五 結語

隨着問題域的複雜性愈來愈高,模塊之間的隔離邊界也有更高的要求,本文從簡單的例子,逐漸演變到服務拆分,從而引出SOFA的模塊化。SOFA基於SpringContext做爲模塊隔離邊界,充分下降了模塊交互的耦合性,同時也爲後續服務拆分提供了便利。

關於SOFA模塊化的實現原理,將另起一文,歡迎關注下方公衆號,更多思考,與你分享。


file

近期文章

分佈式冪等問題解決方案三部曲

Java跨平臺?慎用這些有平臺差別性的方法!

相關文章
相關標籤/搜索