實操|基於阿里巴巴最新開源的分布式SOFABoot 進行模塊化開發

SOFA 中間件是螞蟻金服自主研發的金融級分佈式中間件,包含了構建金融級雲原生架構所需的各個組件,包括微服務研發框架,RPC 框架,服務註冊中心,分佈式定時任務,限流/熔斷框架,動態配置推送,分佈式鏈路追蹤,Metrics監控度量,分佈式高可用消息隊列,分佈式事務框架,分佈式數據庫代理層等組件,是在金融場景裡錘鍊出來的最佳實踐。

SOFABoot 是螞蟻金服中間件團隊開源的基於 Spring Boot 的一個開發框架,SOFABoot 從 2.4.0 版本開始支持基於 Spring 上下文隔離的模塊化開發能力,SOFABoot 模塊除了包括 Java 代碼外,還會包含 Spring 配置文件,每個 SOFABoot 模塊都是獨立的 Spring 上下文。

SOFABoot 的 Github 的地址是:

https://github.com/alipay/sofa-boot

實操|基於阿里巴巴最新開源的分佈式SOFABoot 進行模塊化開發

背景

為了更好的理解 SOFABoot 模塊化開發的概念,我們來區分幾個常見的模塊化形式:

  • 基於代碼組織上的模塊化:這是最常見的形式,在開發期,將不同功能的代碼放在不同 Java 工程下,在編譯期被打進不同 jar 包,在運行期,所有 Java 類都在一個 classpath 下且使用同一個 Spring 上下文,沒做任何隔離;
  • 基於 Spring 上下文隔離的模塊化:使用 Spring 上下文來做不同功能模塊的隔離,在開發期和編譯期,代碼和配置也會分在不同 Java 工程中,但在運行期,不同的 Spring Bean 相互不可見,IoC 只在同一個上下文內部發生,但是所有的 Java 類還是在一個 ClassLoader 下;
  • 基於 ClassLoader 隔離的模塊化:借用 ClassLoader 來做隔離,每個模塊都有獨立的 ClassLoader,模塊與模塊之間的 classpath 不同,SOFAArk 就是這種模塊化的實踐方式。

以上三種模塊化形式的隔離化程度逐次遞進,但模塊化就像一把雙刃劍,在降低模塊間耦合的同時也給模塊間交互增加了成本,本文介紹第二種模塊化形式 — 基於 Spring 上下文隔離的模塊化。

與基於代碼組織上的模塊化相比,每個 SOFABoot 模塊不僅僅包括 Java 代碼,還會包含 Spring 配置文件,這種全新的包組織方式大大降低了用戶接入成本,用戶只需要簡單的引入 Jar 包即可,由 SOFABoot 框架負責刷新模塊上下文,無需在原來 Spring 配置文件中新增任何 Bean 定義,簡化了接入流程,降低了出錯幾率。

每個 SOFABoot 模塊的 Spring 上下文都是隔離的。在 Spring 開發中,保證 Spring BeanId 不衝突是 Spring 運行的基礎,這個限制在應用規模較小時很容易解決,只需用戶在定義 BeanId 時稍加註意即可。

但是隨著系統規模越來越大,一個系統的開發往往涉及多個團隊,保證每個業務定義 BeanId 不重複的成本也越來越高。在 SOFABoot 中,每個 SOFABoot 模塊使用獨立的 Spring 上下文,避免了不同 SOFABoot 模塊間 BeanId 衝突,有效降低企業級多模塊開發時團隊間的溝通成本。

基本原理

在介紹 SOFABoot 模塊化開發使用之前,我們簡單瞭解下其背後的實現原理。下圖是應用運行時的邏輯視圖:

實操|基於阿里巴巴最新開源的分佈式SOFABoot 進行模塊化開發

SOFABoot 模塊是模塊化開發的最小單元,每個 SOFABoot 模塊是一個獨立的 Spring 上下文,在 SOFABoot 模塊中我們可以定義Bean、發佈 RPC 服務、連接數據庫等等。

由於上下文隔離,模塊與模塊之間的 Bean 無法通過 @Autowired 依賴注入,我們提供了 JVM Service/Reference 的方式進行模塊間通信。

SOFABoot 提供了兩種形式的服務發佈和引用,用於解決不同級別的模塊間調用問題:

  • JVM 服務發佈和引用:解決一個 SOFABoot 應用內部各個 SOFABoot 模塊之間的調用問題
  • RPC 服務發佈和引用:解決多個 SOFABoot 應用之間的遠程調用問題

Spring Boot 應用在調用 SpringApplication.run 時會創建一個 Spring Context,我們把它叫做 Root Application Context,它是每個 SOFABoot 模塊創建的 Spring Context 的 Parent。這樣設計的目的是為了保證每個 SOFABoot 模塊的 Spring Context 都能發現 Root Application Context 中創建的 Bean,這樣當應用新增 Starter 時,不僅 Root Application Context 能夠使用 Starter 中新增的 Bean,每個 SOFABoot 模塊的 Spring Context 也能使用這些 Bean。

下面我們來演示如何開發一個簡單的 SOFABoot 模塊

1 新建工程

DEMO 工程地址:

https://github.com/caojie09/sofaboot-module-demo

運行需要 JDK 6 及以上、 Maven 3.2.5 以上。

首先我們在 IDE 裡新建一個普通 Maven 工程,並創建兩個普通的 Maven 模塊:

  • service-facade: 定義服務接口
  • service-provide: 演示新建 SOFABoot 模塊併發布 JVM 服務

2. 定義服務接口

service-facade 模塊包含用於演示 SOFABoot 模塊發佈與引用服務接口:

public interface SampleService {

String message();

}

3. 定義 SOFABoot 模塊

service-provider 是一個 SOFABoot 模塊,它會發佈一個 JVM 服務供其他模塊使用。首先需要為 service-provider 模塊增加 sofa-module.properties 文件,將其定義為 SOFABoot 模塊,sofa-module.properties 文件放置在 resources 目錄:

Module-Name=com.alipay.sofa.service-provider

4. 發佈服務

SOFABoot 支持三種形式的服務發佈,分別是: XML 方式、Annotation 方式以及 API 編碼方式,這裡演示的是 XML 方式發佈服務。

首先增加 SampleServiceImpl 類,實現 SampleService 接口:

public class SampleServiceImpl implements SampleService {

private String message;

public String message() {

return message;

}

public String getMessage() {

return message;

}

public void setMessage(String message) {

this.message = message;

}

}

增加 META-INF/spring/service-provide.xml 文件,將 SampleServiceImpl 發佈為 JVM 服務:

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:sofa="http://sofastack.io/schema/sofaboot"

xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd

http://sofastack.io/schema/sofaboot http://sofastack.io/schema/sofaboot.xsd"

default-autowire="byName">

到此為止,我們就成功新建了一個 SOFABoot 模塊,並在模塊中發佈了一個 JVM 服務,可以看到,一個 SOFABoot 模塊不僅僅包括代碼,還包括 Spring 配置文件。

接下來,在 Spring Boot 工程中,快速集成 SOFABoot 的模塊化開發能力,並使用剛剛新建的模塊發佈的服務

Spring Boot 工程集成模塊化開發組件

1. 新建工程

Demo 工程地址:

https://github.com/caojie09/sofaboot-module-run

在 Spring Boot 官網 https://start.spring.io 新建一個 web 工程,請選擇 Spring Boot 版本號為 1.X,目前不支持 Spring Boot 2。修改 maven 項目的配置文件 pom.xml,將

org.springframework.boot

spring-boot-starter-parent

1.5.14.RELEASE

替換為:

com.alipay.sofa

sofaboot-dependencies

2.4.2

並添加如下依賴:

com.alipay.sofa

isle-sofa-boot-starter

這樣,一個 Spring Boot 工程便集成了 SOFABoot 模塊化開發能力。

2. 添加 SOFABoot 模塊

添加 SOFABoot 模塊很簡單,只需要把 SOFABoot 模塊的座標加在當前 maven 工程即可,對於這個例子,只需要在啟動類模塊添加上面創建的 service-provider 模塊:

com.alipay.sofa

service-provide

1.0.0

與傳統的 JAR 包代碼分發方式相比,SOFABoot 模塊不僅僅包括代碼,還包括 Spring 配置文件,用戶在使用 SOFABoot 模塊時,只需增加依賴即可。

3. 引用服務

為了直觀演示,我們在演示工程增加了一個 Rest 接口,在 Rest 接口中引用上文 SOFABoot 模塊發佈的 JVM 服務。這裡演示的是 Annotation 方式引用服務,只需在類的字段上增加 @SofaReference 註解即可:

@RestController

public class HelloController {

@SofaReference

private SampleService sampleService;

@RequestMapping("/hello-sofamodule")

public String hello() throws IOException {

return sampleService.message();

}

}

訪問 http://localhost:8080/hello-sofamodule,可以看到 HelloController 成功調用到了 service-provider 發佈的服務。

總結

本文主要介紹了使用 SOFABoot 進行上下文隔離的模塊化開發,通過兩個簡單的用例工程,分別介紹瞭如何開發一個 SOFABoot 模塊以及如何在 Spring Boot 快速集成模塊化開發能力。每個 SOFABoot 模塊都是獨立的 Spring 上下文,SOFABoot 模塊不僅僅包括代碼,還包括 Spring 配置文件,用戶在引用 SOFABoot 模塊時,只需簡單增加依賴即可,由框架負責刷新模塊上下文,無需在 Spring 中新增任何 Bean 定義,簡化了接入流程,降低了出錯幾率。


分享到:


相關文章: