金融グレードのアプリケーション開発@SOFABootフレームワークの分析

序文

SOFABootは、AntGroupのオープンソースのSpringBootベースのR&Dフレームワークであり、準備チェック、クラス分離、ログスペース分離などの機能を提供して、Springアプリケーションの迅速で機敏な開発、特にマイクロサービスシステムの構築を実現します。

Spring Bootは、Springの条件付き構成に基づいており、スターター依存関係メカニズムと組み合わせて、Springプロジェクトを開発するための高速で便利なエクスペリエンスを提供し、大きな成功を収めています。

これらの2つの機能に基づいて、SOFABootは、SpringBootに基づく金融グレードのアプリケーション開発のフレームワークを拡張します。AntGroupから生まれたSpringBootの実践として、SOFABootは、準備チェック、クラス分離、ログスペース分離などの大規模な金融生産シナリオにおけるSpringBootの欠点のいくつかを補完し​​ます。SOFABootは、Spring Bootを強化する一方で、ユーザーがSpringBootでSOFAStackミドルウェアを簡単に使用できるようにする機能も提供します。

SOFABoot:github.com/sofastack/s…

ファンクションポイントの概要

SOFABootはSpringBootと完全に互換性があり、SpringBootテクノロジースタックをSOFABootテクノロジースタックにすばやく切り替えることができます。プロジェクトpomが依存するノードを変更します。

たとえば、次のようになります。

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>${spring.boot.version}</version>
    <relativePath />
</parent>
复制代码

と置換する:

<parent>
    <groupId>com.alipay.sofa</groupId>
    <artifactId>sofaboot-dependencies</artifactId>
    <version>${sofa.boot.version}</version>
    <relativePath />
</parent>
复制代码

SOFABootの現在の最新バージョンはv3.11.1です。

準備チェックを適用する

アプリケーションの起動後、外部リクエストを処理する準備はできていますか?

アプリケーショントラフィックのエントリポイントであるコンポーネントは外部接続を受信できますか?

アプリケーションの準備状況チェックを導入する必要があります。SOFABootは、Spring Bootヘルスチェックに加えて、アプリケーションの準備状況チェック機能を提供し、アプリケーションコンポーネントの正常な起動と安全なオンラインを保証します。

SOFABootは、HealthCheckerを介して各コンポーネントの準備状況をチェックします。

在 Spring 上下文刷新完成之后(所有的 Spring Bean 已经实例化完成),SOFABoot 会获取 IoC 容器中所有的 HealthChecker 实现类,检查其返回的组件健康状况。

在应用开启了模块化隔离之后,模块 HealthChecker 还会检查各模块的健康状况。Spring 原生的 HealthIndicator 作为 Readiness 的一部分也会纳入 Readiness 的结果中,若 HealthIndicator 出现了失败的情况,那么应用的 Readiness 也是不通过。

Readiness 检查包含组件的后置检查,流量入口组件(例如:RPC、REST)需要保证后置检查通过之后,能接受外部流量的请求,应用才是真正 ready 了。

应用 Readiness 与 Liveliness 的不同是:

  • Readiness 表示的是应用启动完成之后是否“准备”好的状态,启动完成之后是不变的

  • 两次部署间的 Readiness 的所有请求结果是一致的

应用模块化

应用模块化的方案多种多样。传统方案是以应用功能为边界做模块划分;研发期间,不同职责的类放在不同的模块下,但在运行期间都在同一个 classpath 下,没有任何隔离。

而与传统的模块划分方案不同,人们发现可以利用 Java 的 ClassLoader 机制,将模块与模块间的类完全隔离。

当某个模块需要与另一个模块通信时,可以通过类的导入和导出来实现。OSGi 和 SOFAArk 都是基于 ClassLoader 隔离的模块化实践方案。

传统的模块化方案没有任何的隔离手段,模块间的边界得不到保障,容易出现模块间的紧耦合。而基于 ClassLoader 的模块化方案则过于彻底,研发人员必须十分清楚类的导入与导出、Java 的类加载体系,模块划分的负担转嫁到了普通研发人员身上。

SOFABoot 综合以上两种方案的利弊,引入了介于两者之间的模块化方案:

每个模块有独立的 Spring 上下文,通过上下文的隔离,让不同模块之间的 Bean 的引用无法直接进行,达到模块在运行时的隔离。

这样既保证了不引入过多的复杂性,也避免了没有任何隔离措施的模块边界保障。

如下图所示:

所有的 SOFABoot 模块都会有一个相同的 Spring Context 的 Parent,称之为 Root Application Context。

对于所有模块都需要引入的 Bean,可以选择将其放置于 Root Application Context 中,在所有的模块间共享。此外,SOFABoot 框架提供两种 Spring 上下文隔离方案后的模块间通信能力:

  • JVM 服务的发布和引用:同一个应用内不同模块间的通信
// Publish a JVM service
@Component
@SofaService
public class MyServiceImpl implements MyService {
    // implementation goes here
}
// Reference a JVM service
public class AnyClass {
    @SofaReference
    private MyService myService;
}
复制代码
  • RPC 服务的发布和引用:不同应用间的通信

// Publish a RPC service
@Component
@SofaService(interfaceType = MyService.class, bindings = { @SofaServiceBinding(bindingType = "bolt") })
public class MyServiceImpl implements MyService {
    // implementation goes here
}
// Reference a RPC service
public class AnyClass {
    @SofaReference(binding = @SofaReferenceBinding(bindingType = "bolt"))
    private MyService myService;
}
复制代码

除了通过注解的方式,SOFABoot 还支持 XML 文件和编程 API 的配置方式。

除了模块间通信能力,SOFABoot 还提供:

  • Module-Profile:模块级 Profile 能力,指定模块是否启动
  • 扩展点:利用 Nuxeo Runtime 为 Bean 提供扩展点入口
  • Require-Module:声明模块间依赖关系

应用并行化启动

模块并行化启动

SOFABoot 模块之间的依赖关系可以通过 Require-Module 指定,SOFABoot 会计算模块间的依赖形成一个有向无环图(DAG)。

SOFABoot 按照拓扑关系顺序启动依赖模块,并行启动自由模块。

例如有如下的模块间依赖:

从图中可知,模块 A 必须在模块 B 和 C 之前启动,模块 D 必须在模块 E 之前启动,模块 A 和 D 可以并行启动(开始起点的自由模块)。相对于所有模块共享一个 Spring 上下文的应用,SOFABoot 应用的并行启动能显著加快应用启动速度。

Spring Bean 异步初始化

实际的 Spring/Spring Boot 开发中,Spring Bean 常常需要在初始化过程中执行准备操作,如拉取远程配置、初始化数据源等等。

并且,这些准备操作在 Bean 初始化过程中占据了大量的时间,显著拖慢速度 Spring 上下文刷新速度。然而,Bean 初始化的准备操作与 Bean 的后置处理往往没有强制的前后顺序,是能够并行的。

SOFABoot 捕捉到了这个特点,提供了可配置选项,将 Bean 的 init-method 方法的执行异步化,从而加快 Spring 上下文刷新过程。

如图所示,Spring 在异步执行自定义 init-method 方法之后,马上进行 BeanPostProcessor 的后置处理,相当于“跳过”了最耗时的 init-method 环节。

Spring Bean 异步初始化配置方法:

<!-- 通过将 async-init 设为 true,开启对应 bean 的异步化初始化 -->
<bean id="testBean" class="com.alipay.sofa.beans.TimeWasteBean" init-method="init" async-init="true"/>
复制代码

中间件集成管理

SOFABoot 通过 starter 机制管理了中间件依赖。

一个中间件的使用不用再引入一长串 JAR 包依赖,而只需要一个 starter 依赖,将中间件当作可独立插拔的“插件”;starter 依赖负责传递中间件需要的 JAR 包依赖。

中间件 starter 版本与 SOFABoot 版本关联,并且保证这些中间件 starter 版本的传递依赖经过严格测试是互相兼容的。不过 SOFABoot 的依赖管理依然是弱管理,如果用户想要指定某个 JAR 包的版本,那么也可以覆盖 starter 中配置的版本。

SOFABoot 支持 Maven 和 Gradle 的依赖配置方式。

日志隔离

SOFABoot 通过 sofa-common-tools 集成了日志空间的隔离能力。

框架自动发现应用中的日志实现,避免中间件和应用日志实现的绑定。

二方包或者引入的中间件面向日志编程接口 SLF4J 去编程,具体的日志实现交给 SOFABoot 应用开发者去选择;同时二方包或者中间件针对每一个日志实现提供配置以输出日志到相对固定目录下的文件。

应用选择的日志实现,框架都能够自动感知并选择相应的配置文件日志输出。

应用类隔离

SOFABoot 通过 SOFAArk 提供类隔离能力和应用合并部署能力。

SOFAArkは分離されたクラス読み込みモデルを使用し、基盤となるプラグインとビジネスアプリケーションは実行時に互いに分離されます。単一のプラグインとアプリケーションは、異なるClassLoaderによって読み込まれます。これにより、相互のパッケージの競合を効果的に回避し、プラグインとモジュールの機能再利用機能。

複数のアプリケーションの組み合わせ展開をサポートします。開発フェーズでは、複数のアプリケーションが実行可能なFat Jarsにパッケージ化され、実行時にAPIまたは構成センターを使用してアプリケーションが動的にインストールおよびアンインストールされます。

おすすめ

転載: juejin.im/post/7085647665517559845