1. 程式人生 > >談談我對SOFA模組化的理解

談談我對SOFA模組化的理解

今天我們談談SOFA模組化,首先看一段SOFA的介紹:

SOFABoot是螞蟻金服開源的基於Spring Boot的研發框架,它在Spring Boot的基礎上,提供了諸如 Readiness Check,類隔離,日誌空間隔離等能力。在增強了Spring Boot的同時,SOFABoot提供了讓使用者可以在Spring Boot中非常方便地使用SOFA中介軟體的能力。

在接觸SOFA的模組化概念之前,我對服務端開發的模組化認知停留在“模組化”這個層面,我通常會按照下圖所示的結構組織自己負責的應用的程式碼。

在Spring體系中的模組(Module),就是通過不同的Spring上下文來管理各自模組中的bean,在開發和編譯期實現模組化,但是在執行時整個應用還是在一個Spring上下文中,這些程式碼還都是被一個類載入器載入的。

在圖1中,我在manager模組中定義的bean,在service中可以隨時引用,而不需要關注這個引用是否合理;這樣的開發模式在應用還小的時候沒什麼問題,不過,隨著業務的發展和應用的升級,這些模組之間的引用關係會越來越複雜而無法管理(這時候應用也就成為了一個“大泥球”),當某一天需要對應用進行服務化拆分的時候,就需要花很大的精力去理清不同模組之間的耦合和引用關係。SOFA的模組化特性就是為了解決這個問題而出現的,這種特性可以強制開發者在增加兩個模組之間的引用關係的時候進行仔細的設計和思考。

SOFA的模組化

SOFA的模組,是一種可執行的模組;普通的Spring專案中的模組,則是普通的Jar。一個完整的 SOFA模組和一個普通的Jar包有兩點區別:

  • SOFA模組包含一份sofa-module.properties檔案,這份檔案裡面定義了SOFA模組的名稱以及模組之間的依賴關係。
  • SOFA模組的META-INF/spring目錄下,可以放置任意多的Spring配置檔案,SOFA會自動把它們作為本模組的Spring配置載入起來。

使用SOFA模組化特性後,兩個模組之間的bean無法直接通訊,需要使用SOFA的通訊協議進行通訊,SOFA支援兩種通訊協議:

  • jvm呼叫,兩個模組是在同一個JVM虛擬機器中執行,無需經過網路呼叫。
  • rpc呼叫,兩個模組不是在同一個JVM虛擬機器中執行,甚至不是在一臺機器上,需要經過網路呼叫。

SOFA為開發人員提供了三種形式的釋出和引用服務的方式:xml方式、註解方式、程式設計方式。我現在用的比較多的還是xml方式,原因在於SofaService和SofaReference都是隻支援jvm服務的釋出和引用,而xml方式則可以支援兩種形式的呼叫。

SOFA模組化對開發模式的影響

SOFA提供的模組化解決方案,既實現了真正的、執行時的模組化,又沒有過度引入OSGI的複雜度,是一種有效的折衷方案。接觸SOFA到熟悉SOFA的過程對我的開發思路影響很大,但是在熟悉了SOFA的模組化思想之後,我發現這個特性對於我平常的開發工作有幾個好處。

安全的近遠端架構

為了降低服務端的壓力,我們需要提供一個SDK供業務方使用,在之前Spring體系下,這種架構也是可以執行的,但是有個弊端——SDK中應用的類和JAR包對於業務方的應用來說也是可見的,在某些情況下會出現衝突或引入潛在的BUG。

使用SOFA的模組化特性,我們提供的近端包雖然還是跟業務方的應用共享一個JVM,但是在類載入器層面實現了隔離,對於業務方來說,他們只需要知道是使用了我們的哪些介面,而不需要關注我們這個SDK引入了多少三方JAR包。

更好的程式碼共享

利用SOFA模組化,要實現程式碼共享,可沒有Spring體系下那麼簡單——直接引用給一個模組就可以。在SOFA中,要進行程式碼共享,通常有兩種情況:(1)近遠端程式碼共享(2)管理時和執行時程式碼共享。

以第(1)種情況為例,某個元件近遠端都是一樣的,為了避免程式碼重複,我們如何實現程式碼共享呢?我現在的做法是:在一個公共的test-core模組中定義需要共享的介面和實現類;這個test-core模組不能定義為SOFA的模組,只能定義為一個普通的JAR包;然後在需要使用該介面的SOFA模組(近端模組和遠端模組)中,分別宣告和引用那個共享的bean,示例圖如下所示。

這裡的重點在於:

  • javaadu-core模組中是一個普通的JAR模組,只有介面的定義和實現,在這個模組中沒有對bean的宣告
  • javaadu-remote模組中是一個SOFA模組,在這裡引用了javaadu-core中的介面和實現,這裡需要對bean進行宣告(bean宣告)和釋出(sofa-service),當前應用的其他模組要想使用該介面,只需要引用javaadu-core和javaadu-remote,然後使用sofa-reference引用該介面就可以,這裡一般是jvm呼叫;其他應用如果想使用該介面,並且沒有近端需求的話,則需要引用javaadu-core和javaadu-remote,並使用sofa-reference引用。可以看出,SOFA模糊了跨應用呼叫和應用內呼叫的概念,模組化做得很徹底
  • javaadu-client模組是一個SOFA模組,也是近端模組,在這裡也需要自己定義和使用javaadu-core中的介面和實現。

總結

本文主要介紹了SOFA開發框架與Spring體系區別最明顯的一個特性:SOFA模組化,通過每個模組一個Spring上下文的形式,實現了真正的執行時隔離。

基於我個人的使用經驗,SOFA模組化對服務端開發的影響優大於劣:在維護程式碼中的過程中會仔細斟酌當前應用的模組依賴結構是否合理;可以更安全得提供SDK給業務方使用;在實現程式碼共享的時候,也需要仔細考慮哪些程式碼值得共享,哪些不需要。

參考資料

  1. Sofaboot-模組化開發概述
  2. 螞蟻金服的業務系統模組化之模組化隔離方案
  3. 阿里巴巴Java開發手冊(華山版).pdf
  4. JVM服務釋出與引用
    ***
    本號(javaadu)專注於後端技術、JVM問題排查和優化、Java面試題、個人成長和自我管理等主題,為讀者提供一線開發者的工作和成長經驗,期待你能在這裡有所收穫。