foreword
SOFABoot is an open-source Spring Boot-based R&D framework of Ant Group, which provides capabilities such as Readiness Check, class isolation, and log space isolation for rapid and agile development of Spring applications, especially for building microservice systems.
Spring Boot is based on Spring's Conditional Configuration, combined with the starter dependency mechanism to provide a fast and convenient experience for developing Spring projects, and has achieved great success.
Based on these two capabilities, SOFABoot extends the framework for financial-grade application development based on Spring Boot. As the practice of Spring Boot born out of Ant Group, SOFABoot supplements some of the shortcomings of Spring Boot in large-scale financial production scenarios, such as readiness checking, class isolation, and log space isolation. While enhancing Spring Boot, SOFABoot also provides the ability for users to easily use SOFAStack middleware in Spring Boot.
SOFABoot: https://github.com/sofastack/sofa-boot
Overview of function points
SOFABoot is fully compatible with Spring Boot, and the Spring Boot technology stack can be quickly switched to the SOFABoot technology stack: modify the <parent/> node that the project pom depends on.
For example would:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>${spring.boot.version}</version>
<relativePath />
</parent>
Replace with:
<parent>
<groupId>com.alipay.sofa</groupId>
<artifactId>sofaboot-dependencies</artifactId>
<version>${sofa.boot.version}</version>
<relativePath />
</parent>
The current latest version of SOFABoot is v3.11.1.
Apply Readiness Check
After an application starts, is it "ready" to handle external requests?
Can the component that is the entry point for application traffic receive external connections?
It is necessary to introduce application readiness check. SOFABoot provides readiness check capabilities of applications in addition to Spring Boot health check to ensure the normal startup and safe online of application components.
SOFABoot checks the readiness of each component through HealthChecker.
After the Spring context refresh is completed (all Spring Beans have been instantiated), SOFABoot will obtain all the HealthChecker implementation classes in the IoC container and check the health status of the returned components.
After the application has turned on modular isolation, the module HealthChecker also checks the health of each module. Spring's native HealthIndicator, as part of Readiness, will also be included in the result of Readiness. If HealthIndicator fails, the application's Readiness will also fail.
Readiness checks include post-checks of components. Traffic entry components (such as RPC, REST) need to ensure that after passing the post-checks, they can accept requests from external traffic, and the application is truly ready.
The difference between applying Readiness and Liveliness is:
- Readiness indicates whether the application is "ready" after the startup is completed, and it remains unchanged after the startup is completed.
- All requests for Readiness between two deployments are consistent
Application Modularity
There are various options for applying modularity. The traditional solution is to divide modules based on application functions; during development, classes with different responsibilities are placed under different modules, but they are all under the same classpath during operation without any isolation.
Different from the traditional module division scheme, people find that the ClassLoader mechanism of Java can be used to completely isolate the modules from the classes between the modules.
When a module needs to communicate with another module, it can be achieved by importing and exporting classes. Both OSGi and SOFAArk are modular practices based on ClassLoader isolation.
The traditional modular solution does not have any means of isolation, the boundaries between modules cannot be guaranteed, and tight coupling between modules is prone to occur. The modular solution based on ClassLoader is too thorough. R&D personnel must be very clear about the import and export of classes and the Java class loading system. The burden of module division is transferred to ordinary R&D personnel.
SOFABoot combines the advantages and disadvantages of the above two solutions and introduces a modular solution between the two:
Each module has an independent Spring context. Through the isolation of the context, the reference of beans between different modules cannot be directly carried out, so as to achieve the isolation of modules at runtime.
This not only ensures that too much complexity is not introduced, but also avoids module boundary guarantees without any isolation measures.
As shown below:
All SOFABoot modules will have an identical Spring Context Parent, called the Root Application Context.
For beans that all modules need to import, you can choose to place them in the Root Application Context and share them among all modules. In addition, the SOFABoot framework provides inter-module communication capabilities after two Spring context isolation schemes:
- Publishing and referencing JVM services: communication between different modules within the same application
// 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;
}
- Publishing and referencing RPC services: communication between different applications
// 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;
}
In addition to annotations, SOFABoot also supports the configuration of XML files and programming APIs.
In addition to inter-module communication capabilities, SOFABoot also provides:
- Module-Profile: Module-level Profile capability, specifying whether the module is started
- Extension Points: Using Nuxeo Runtime to provide extension point entry for beans
- Require-Module: declare dependencies between modules
Application parallelization startup
module parallelization start
The dependencies between SOFABoot modules can be specified through Require-Module, and SOFABoot will calculate the dependencies between modules to form a directed acyclic graph (DAG).
SOFABoot starts dependent modules in topological order, and starts free modules in parallel.
For example, there are the following inter-module dependencies:
As can be seen from the figure, module A must be started before modules B and C, module D must be started before module E, and modules A and D can be started in parallel (free modules at the starting point). Compared with applications where all modules share a Spring context, the parallel startup of SOFABoot applications can significantly speed up application startup.
Asynchronous initialization of Spring Beans
In actual Spring/Spring Boot development, Spring Beans often need to perform preparatory operations during the initialization process, such as pulling remote configuration, initializing data sources, and so on.
Moreover, these preparation operations occupy a lot of time in the bean initialization process, which significantly slows down the refresh speed of the Spring context. However, the preparation operation of bean initialization and the post-processing of bean often do not have a mandatory sequence, and can be parallelized.
SOFABoot captures this feature and provides configurable options to asynchronously execute the Bean's init-method method, thereby speeding up the Spring context refresh process.
As shown in the figure, after Spring executes the custom init-method method asynchronously, it immediately performs post-processing of the BeanPostProcessor, which is equivalent to "skipping" the most time-consuming init-method link.
Spring Bean asynchronous initialization configuration method:
<!-- 通过将 async-init 设为 true,开启对应 bean 的异步化初始化 -->
<bean id="testBean" class="com.alipay.sofa.beans.TimeWasteBean" init-method="init" async-init="true"/>
Middleware Integration Management
SOFABoot manages middleware dependencies through the starter mechanism.
The use of a middleware does not need to introduce a long list of JAR package dependencies, but only needs a starter dependency, treating the middleware as an independently pluggable "plug-in"; the starter dependency is responsible for delivering the JAR package dependencies required by the middleware.
The middleware starter version is associated with the SOFABoot version, and the transitive dependencies of these middleware starter versions are strictly tested to be compatible with each other. However, SOFABoot's dependency management is still weak management. If users want to specify the version of a JAR package, they can also override the version configured in the starter.
SOFABoot supports the dependency configuration of Maven and Gradle.
log isolation
SOFABoot integrates log space isolation capabilities through sofa-common-tools.
The framework automatically discovers the log implementation in the application, avoiding the binding of the middleware and the application log implementation.
The second-party package or the introduced middleware is programmed for the log programming interface SLF4J, and the specific log implementation is left to the SOFABoot application developer to choose; at the same time, the second-party package or middleware provides configuration for each log implementation to output logs to a relatively fixed directory file below.
By applying the selected log implementation, the framework can automatically perceive and select the corresponding configuration file log output.
Application class isolation
SOFABoot provides class isolation capability and application merge deployment capability through SOFAArk.
SOFAArk uses an isolated class loading model, and the underlying plug-ins and business applications are isolated from each other at runtime. A single plug-in and application are loaded by different ClassLoaders, which can effectively avoid package conflicts between each other and improve the function reuse capability of plug-ins and modules.
Supports the combined deployment of multiple applications. In the development phase, multiple applications are packaged into executable Fat Jars, and the applications are dynamically installed and uninstalled using the API or configuration center at runtime.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。