談談我對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服務發佈與引用

本號專注於後端技術、JVM問題排查和優化、Java面試題、個人成長和自我管理等主題,爲讀者提供一線開發者的工作和成長經驗,期待你能在這裏有所收穫。javaadu

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章