SOFA 中间件是蚂蚁金服自主研发的金融级分布式中间件,包含了构建金融级云原生架构所需的各个组件,包括微服务研发框架,RPC 框架,服务注册中心,分布式定时任务,限流/熔断框架,动态配置推送,分布式链路追踪,Metrics监控度量,分布式高可用消息队列,分布式事务框架,分布式数据库代理层等组件,是在金融场景里锤炼出来的最佳实践。git
SOFABoot 是蚂蚁金服中间件团队开源的基于 Spring Boot 的一个开发框架,SOFABoot 从 2.4.0 版本开始支持基于 Spring 上下文隔离的模块化开发能力,SOFABoot 模块除了包括 Java 代码外,还会包含 Spring 配置文件,每一个 SOFABoot 模块都是独立的 Spring 上下文。github
SOFABoot 的 Github 的地址是:web
https://github.com/alipay/sofa-boot spring
为了更好的理解 SOFABoot 模块化开发的概念,咱们来区分几个常见的模块化形式:数据库
基于代码组织上的模块化:这是最多见的形式,在开发期,将不一样功能的代码放在不一样 Java 工程下,在编译期被打进不一样 jar 包,在运行期,全部 Java 类都在一个 classpath 下且使用同一个 Spring 上下文,没作任何隔离;bash
基于 Spring 上下文隔离的模块化:使用 Spring 上下文来作不一样功能模块的隔离,在开发期和编译期,代码和配置也会分在不一样 Java 工程中,但在运行期,不一样的 Spring Bean 相互不可见,IoC 只在同一个上下文内部发生,可是全部的 Java 类仍是在一个 ClassLoader 下;架构
基于 ClassLoader 隔离的模块化:借用 ClassLoader 来作隔离,每一个模块都有独立的 ClassLoader,模块与模块之间的 classpath 不一样,SOFAArk 就是这种模块化的实践方式。并发
以上三种模块化形式的隔离化程度逐次递进,但模块化就像一把双刃剑,在下降模块间耦合的同时也给模块间交互增长了成本,本文介绍第二种模块化形式 — 基于 Spring 上下文隔离的模块化。app
与基于代码组织上的模块化相比,每一个 SOFABoot 模块不单单包括 Java 代码,还会包含 Spring 配置文件,这种全新的包组织方式大大下降了用户接入成本,用户只须要简单的引入 Jar 包便可,由 SOFABoot 框架负责刷新模块上下文,无需在原来 Spring 配置文件中新增任何 Bean 定义,简化了接入流程,下降了出错概率。框架
每一个 SOFABoot 模块的 Spring 上下文都是隔离的。在 Spring 开发中,保证 Spring BeanId 不冲突是 Spring 运行的基础,这个限制在应用规模较小时很容易解决,只需用户在定义 BeanId 时稍加注意便可。
可是随着系统规模愈来愈大,一个系统的开发每每涉及多个团队,保证每一个业务定义 BeanId 不重复的成本也愈来愈高。在 SOFABoot 中,每一个 SOFABoot 模块使用独立的 Spring 上下文,避免了不一样 SOFABoot 模块间 BeanId 冲突,有效下降企业级多模块开发时团队间的沟通成本。
在介绍 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。
DEMO 工程地址:
https://github.com/caojie09/sofaboot-module-demo
运行须要 JDK 6 及以上、 Maven 3.2.5 以上。
首先咱们在 IDE 里新建一个普通 Maven 工程,并建立两个普通的 Maven 模块:
service-facade: 定义服务接口
service-provide: 演示新建 SOFABoot 模块并发布 JVM 服务
service-facade 模块包含用于演示 SOFABoot 模块发布与引用服务接口:
public interface SampleService {
String message();
}复制代码
service-provider 是一个 SOFABoot 模块,它会发布一个 JVM 服务供其余模块使用。首先须要为 service-provider 模块增长 sofa-module.properties 文件,将其定义为 SOFABoot 模块,sofa-module.properties 文件放置在 resources 目录:
Module-Name=com.alipay.sofa.service-provider复制代码
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 服务:
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"
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">
<bean id="sampleService" class="com.alipay.sofa.isle.sample.SampleServiceImpl">
<property name="message" value="Hello, SOFABoot module."/>
</bean>
<sofa:service ref="sampleService" interface="com.alipay.sofa.isle.sample.SampleService">
<sofa:binding.jvm/>
</sofa:service>
</beans>复制代码
到此为止,咱们就成功新建了一个 SOFABoot 模块,并在模块中发布了一个 JVM 服务,能够看到,一个 SOFABoot 模块不单单包括代码,还包括 Spring 配置文件。
接下来,在 Spring Boot 工程中,快速集成 SOFABoot 的模块化开发能力,并使用刚刚新建的模块发布的服务
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,将
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.14.RELEASE</version>
<relativePath/>
</parent>复制代码
替换为:
<parent>
<groupId>com.alipay.sofa</groupId>
<artifactId>sofaboot-dependencies</artifactId>
<version>2.4.2</version>
</parent>复制代码
并添加以下依赖:
<dependency>
<groupId>com.alipay.sofa</groupId>
<artifactId>isle-sofa-boot-starter</artifactId>
</dependency>复制代码
这样,一个 Spring Boot 工程便集成了 SOFABoot 模块化开发能力。
添加 SOFABoot 模块很简单,只须要把 SOFABoot 模块的坐标加在当前 maven 工程便可,对于这个例子,只须要在启动类模块添加上面建立的 service-provider 模块:
<dependency>
<groupId>com.alipay.sofa</groupId>
<artifactId>service-provide</artifactId>
<version>1.0.0</version>
</dependency>复制代码
与传统的 JAR 包代码分发方式相比,SOFABoot 模块不单单包括代码,还包括 Spring 配置文件,用户在使用 SOFABoot 模块时,只需增长依赖便可。
为了直观演示,咱们在演示工程增长了一个 Rest 接口,在 Rest 接口中引用上文 SOFABoot 模块发布的 JVM 服务。这里演示的是 Annotation 方式引用服务,只需在类的字段上增长
@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 定义,简化了接入流程,下降了出错概率。
你也许感兴趣:
开源 | 在 Spring Boot 中集成 SOFABoot 类隔离能力
长按关注,获取最新分布式架构干货
欢迎你们共同打造 SOFAStack https://github.com/alipay