SOFABoot-02-模块化隔离方案

sofaboot

前言

大家好,我是老马。

sofastack 其实出来很久了,第一次应该是在 2022 年左右开始关注,但是一直没有深入研究。

最近想学习一下 SOFA 对于生态的设计和思考。

sofaboot 系列

SOFABoot-00-sofaboot 概览

SOFABoot-01-蚂蚁金服开源的 sofaboot 是什么黑科技?

SOFABoot-02-模块化隔离方案

SOFABoot-03-sofaboot 介绍

SOFABoot-04-快速开始

SOFABoot-05-依赖管理

SOFABoot-06-健康检查

SOFABoot-07-版本查看

SOFABoot-08-启动加速

SOFABoot-09-模块隔离

SOFABoot-10-聊一聊 sofatboot 的十个问题

蚂蚁金服的业务系统模块化之模块化隔离方案

无论是什么样的业务系统,多多少少都会去做一些模块化的划分,或横或纵,各种姿势,但是这些姿势真地能帮你划分出良好的模块吗?

帮你在模块之间做到高内聚,低耦合吗?

模块化对于服务化又有什么样的影响?

本来将分析常见的几种模块化方案的利弊,并且介绍蚂蚁金服开源的框架 SOFA 在模块化中发挥的作用。

传统模块化的陷阱

在一个简单的 Spring/SpringBoot 的系统中,我们常常见到一个系统中的模块会按照如下的方式进行分层,如下图中的左边部分所示,一个系统就简单地分为 Web 层、Service 层、DAL 层。

传统模块化

当这个系统承载的业务变多了之后,系统可能演化成上图中右边的这种方式。

在上图的右边的部分中,一个系统承载了两个业务,一个是 Cashier(收银台),另一个是 Pay(支付),这两个业务可能会有一些依赖的关系,Cashier 需要调用 Pay 提供的能力去做支付。

但是在这种模块化的方案里面,Spring 的上下文依然是同一个,类也没有任何做隔离,这就意味着,Pay Service 这个模块里面的任何的一个 Bean,都可以被 Cashier Service 这个模块所依赖。

极端的情况下,可能会出现下面这种情况:

极端情况

Cashier Service 错误地调用了 Pay Service 中的一个内部的 Bean,造成了两个模块之间的紧耦合。

这种传统的模块化的问题在于模块化地不彻底。

虽然在研发的时候,通过划分模块,把特定职责的类放到特定的模块里面去,达到了类的「物理位置」的内聚。

但是在运行时,由于没有做任何隔离的手段,作为一个模块的开发者,并没有办法清楚地知道对方模块提供的对外的接口到底是什么,哪些 Bean 我是可以直接注入来用的,哪些 Bean 是你的内部的 Bean,我是不能用的。

长此以往,模块和模块之间的耦合就会越来越严重,原来的模块的划分形同虚设。

当系统越来越大,最后需要做服务化拆分的时候,就需要花费非常大的精力去梳理模块和模块之间的关系。

OSGi 模块化

提到模块化,不得不提 OSGi,虽然 OSGi 没有成为 Java 官方的模块化的标准,但是由于 Java 在 Java 9 之前,一直没有官方的模块化的标准,所以 OSGi 已经是事实上的标准。

OSGi 为模块化主要做了两个事情:

  • OSGi 的类隔离

  • OSGi 的声明式服务

下面就给读者们简单地解释一下 OSGi 的这两个方面。

OSGi 的类隔离

OSGi 通过扩展 Java 的 ClassLoader 机制,将模块和模块之间的类完全隔离开来,当一个模块需要引用另一个模块的类的时候,通过在模块中的 MANIFEST.MF 文件中声明类的导出和导入来解决,如下图所示:

OSGI

通过这种方式,可以控制一个模块特定的类才可以被另一个模块所访问,达到了一定程度地模块的隔离。

但是,光光通过类的导出导入来解决类的引用问题还不够,还需要去解决实例的引用的问题,我们往往希望能够直接使用对方模块提供的某一个类的实例,而不是自己去 new 一个实例出来,所以 OSGi 还提供了声明式服务的方式,让一个模块可以引用到另一个模块提供的服务。

OSGi 的声明式服务

OSGi 的声明式服务正是为了解决这个实例引用的问题,我们可以在一个 OSGi 的模块(Bundle)中去添加一个 XML 配置文件去声明一个服务,如下面的代码所示:

<?xml version="1.0" encoding="UTF-8"?>
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="ITodoService"><implementation class="com.example.e4.rcp.todo.service.internal.MyTodoServiceImpl"/><service><provide interface="com.example.e4.rcp.todo.model.ITodoService"/></service>
</scr:component>

也可以同样的通过 XML 配置文件去引用一个其他的模块声明的服务:

<?xml version="1.0" encoding="UTF-8"?>
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="XXXService"><reference name="ITodoService"interface="com.example.e4.rcp.todo.model.ITodoService"bind="setITodoService" cardinality="0..1" unbind="unsetITodoService"policy="dynamic" /><implementation class="com.example.e4.rcp.todo.service.internal.XXXServiceImpl"/>
</scr:component>

通过声明式服务的方式,我们就可以直接在一个 OSGi 的 Bundle 中使用另一个 Bundle 中提供的服务实例了。

OSGi 的模块化的问题

OSGi 通过类隔离的机制解决了模块之间的类隔离的问题,然后通过声明式服务的方式解决了模块之间的服务调用的问题,看起来已经完美的解决了我们在传统的模块化中遇到的问题,通过这两个机制,模块和模块之间的边界变得清晰了起来。

但是在实践的过程中,OSGi 的模块化却面临着一个非常严峻的问题,这个就是就是 OSGi 的类隔离带来的复杂性,OSGi 把每一个模块都通过独立的 ClassLoader 去加载,这样在开发模块的时候,研发的同学就必须非常清楚地去定义哪些类应该导出,哪些类应该导入,一旦少导出,或者导出错误,就会出现各种各样的错误,比如 LinkageError,NoSuchMethodError 等等,而要解决这些错误,要求研发同学清楚地理解 OSGi 的整个类加载体系,以及 Java 的整个类加载体系,这对普通的研发同学来说实在是一个太高的要求

所以这种方式在实施成本非常高,OSGi 并不是非常适合于业务研发。

SOFA 模块化

为了解决传统的模块化方案模块化不彻底的问题,以及 OSGi 的彻底的模块化带来的复杂性的问题,SOFA 在早期就开始引入了一种折衷的模块化的方案。

SOFA 模块化的整体的示意图如下:

sofa

SOFA 模块化的方案,给每一个模块都提供了一个单独的 Spring 的上下文,通过 Spring 上下文的隔离,让模块和模块之间的 Bean 的引用无法直接进行,达到模块在运行时隔离的能力。

当一个模块需要调用另一个模块里面的一个 Bean 的时候,SOFA 采用了类似于 OSGi 的声明式的服务的方式,提供服务的模块可以在其配置文件(也可以通过 Annotation 的方式来声明)中声明一个 SOFA Service:

<sofa:service ref="sampleBean" interface="com.alipay.sofaboot.SampleBean"/>

使用服务的模块可以在其配置文件(也可以通过 Annotation 来使用)声明一个 SOFA Reference:

<sofa:reference id="sampleBean" interface="com.alipay.sofaboot.SampleBean"/>

通过这种方式,一个模块就可以清晰地知道它提供了哪些服务,引用了哪些服务,和其他的模块之间的关系也就非常清楚了。

但是 SOFA 的模块化方案中并没有引入类隔离的方案,这也是为了避免研发的同学去处理太复杂的类加载的问题,简化研发的成本。

通过 SOFA 模块化做快速地服务化

上面已经讲到,通过 SOFA 的模块化的方案,我们就可以非常清楚地知道一个模块的边界在哪里,它依赖了哪些服务,它又发布了哪些服务。当你的应用膨胀到需要去做服务化的时候,这样,拆分起来就非常简单了。

而 SOFA 在这个上面其实做了一件更加方便大家做服务拆分的事情,就是 SOFA 的模块之间的服务发布和服务引用和 SOFA 的应用之间的服务的发布和引用的编程模型以及接口是一致的。

SOFA 模块化

如上图所示,当原来包含了 Cashier 和 Pay 两个能力的系统需要拆分成两个系统的时候,只需要在原来声明 SOFA Service 和 SOFA Reference 的地方,加上一个协议的声明就行,比如,原来发布的服务是下面这样:

<sofa:service ref="sampleBean" interface="com.alipay.sofaboot.SampleBean"/>

只需要修改成:

<sofa:service ref="sampleBean" interface="com.alipay.sofaboot.SampleBean"><sofa:binding.bolt/>
</sofa:service>

原来引用服务是下面这样:

<sofa:reference id="sampleBean" interface="com.alipay.sofaboot.SampleBean"/>

只需要修改成:

<sofa:reference id="sampleBean" interface="com.alipay.sofaboot.SampleBean"><sofa:binding.bolt/>
</sofa:reference>

事实上,这种快速的服务化拆分的方式,也在蚂蚁金服整个架构往服务化转型的过程中提供了极大的便利。

小结

希望本文对你有所帮助,如果喜欢,欢迎点赞收藏转发一波。

我是老马,期待与你的下次相遇。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/38183.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【实用部署教程】olmOCR智能PDF文本提取系统:从安装到可视化界面实现

文章目录 引言系统要求1. 环境准备&#xff1a;安装Miniconda激活环境 2. 配置pip源加速下载3. 配置学术加速&#xff08;访问国外资源&#xff09;4. 安装系统依赖5. 安装OLMOCR6. 运行OLMOCR处理PDF文档7. 理解OLMOCR输出结果9. 可视化UI界面9.1 安装界面依赖9.2 创建界面应用…

asp.net core mvc模块化开发

razor类库 新建PluginController using Microsoft.AspNetCore.Mvc;namespace RazorClassLibrary1.Controllers {public class PluginController : Controller{public IActionResult Index(){return View();}} }Views下Plugin下新建Index.cshtml {ViewBag.Title "插件页…

边缘计算革命:重构软件架构的范式与未来

摘要 边缘计算通过将算力下沉至网络边缘&#xff0c;正在颠覆传统中心化软件架构的设计逻辑。本文系统分析了边缘计算对软件架构的范式革新&#xff0c;包括分布式分层架构、实时资源调度、安全防护体系等技术变革&#xff0c;并结合工业物联网、智慧医疗等场景案例&#xff0c…

单链表:数据结构的灵动之链

本文主要讲解链表的概念和结构以及实现单链表 目录 一、链表的概念及结构 二、单链表的实现 1.1链表的实现&#xff1a; 1.2单链表的实现&#xff1a; 单链表尾插&#xff1a; 单链表的头插&#xff1a; 单链表的尾删&#xff1a; 单链表头删&#xff1a; 单链表查找&#…

链表题型-链表操作-JS

一定要注意链表现在的头节点是空节点还是有值的节点。 一、移除链表中的元素 有两种方式&#xff0c;直接使用原来的链表进行删除操作&#xff1b;设置一个虚拟头节点进行删除操作。 直接使用原来的链表进行删除操作时&#xff0c;需要考虑是不是头节点&#xff0c;因为移除…

读《浪潮之巅》:探寻科技产业的兴衰密码

引言&#xff1a;邂逅《浪潮之巅》 在信息技术飞速发展的今天&#xff0c;科技公司如繁星般闪烁&#xff0c;又似流星般划过。而我与《浪潮之巅》的相遇&#xff0c;就像在浩渺的科技海洋中&#xff0c;发现了一座指引方向的灯塔。初次听闻这本书&#xff0c;是在一次技术交流会…

【和春笋一起学C++】文本文件I/O

在windows系统中读取键盘的输入和在屏幕上显示输出统称为&#xff1a;控制台输入/输出。把读取文本文件和把字符输出到文本文件中统称为&#xff1a;文本文件I/O。 目录 1. 输出文本文件 2. 读取文本文件 1. 输出文本文件 把字符输出到文本文件中和输出到控制台很相似&#x…

【C#】WinForm自定义控件及窗体

前言 WinForm&#xff08;Windows Forms&#xff09;是Microsoft.NET框架中的技术&#xff0c;用于开发Windows桌面应用程序。它提供了一套丰富的控件和组件。通过拖放控件、编写事件处理程序等方式快速构建用户界面。 通过属性窗口定制这些控件的外观和行为。 通过数据绑定&am…

Live555+Windows+MSys2 编译Androidso库和运行使用

下载 wget http://www.live555.com/liveMedia/public/live555-latest.tar.gz tar -xzvf live555-latest.tar.gz加入版本控制 git init git add . git commit -a -m "first init" git log修改config.android-arm64 cd live vim config.android-arm64 ./genMakefile…

大模型-提示词工程与架构

什么是提示工程 提示工程&#xff08;Prompt Engineering&#xff09;是一门新兴的技术领域&#xff0c;专注于研究如何设计、构建和优化提示词&#xff0c;以充分发挥大模型的潜力 。它涉及到对语言结构、任务需求、模型特性等多方面因素的综合考量。提示工程的目标是通过精心…

Agent Team 多智能体系统解析

引言 在人工智能技术高速发展的今天&#xff0c;"多智能体协作系统"&#xff08;Agent Team&#xff09;正成为突破效率瓶颈的关键技术。与传统的单体AI不同&#xff0c;这种由多个专业化智能体组成的协同网络&#xff0c;通过分工协作和动态调整&#xff0c;展现出…

【蓝桥杯—单片机】IAP15F2K61S2专项 | 真题整理、解析与拓展 | 省赛题(更新ing...)

IAP15F2K61S2 专项 前言IAP15F2K61S2 介绍&#xff08;基于手册&#xff09;I/O口结构复位管脚RST中断第十四届省赛 外设通过PWM控制第十五届省赛题 性能与工作参数在线调试第十四届省赛题拓展与小结&#xff1a;单片机在线调试常用的接口 功耗第十五届省赛题 前言 在本文中我…

生物化学笔记:医学免疫学原理02 抗原概念+免疫应答+抗原的分类

抗原基本概念 影响抗原刺激机体产生免疫应答的因素 抗原的分类 CG 【北京大学】1080p 王月丹教授 《医学免疫学原理》2022春 全81p

(UI自动化测试)第二篇:元素定位的方法_name定位

二、name定位 ⽅法&#xff1a; driver.find_element_by_name(“name属性值”) 前置&#xff1a; 标签必须name属性 特点&#xff1a; 当前⻚⾯可以重复 提示&#xff1a; 由于name属性值可以重复&#xff0c;所以使⽤时需要查看是否为唯⼀。 # 导包selenium from selenium i…

软考中级-软件设计师 准备

软考中级-软件设计师 准备 一、软考相关1.1、考试时间1.2、考试时长1.3、题型和分值&#xff1a; 二、软考备考2.1、相关书籍2.2、推荐课程&#xff1a;B站up主zst_20012.3、学习路线 一、软考相关 1.1、考试时间 一年有两次软考&#xff0c;一般是五月末和十一月的中旬 以下…

记忆力训练day24

一 数字锁链串联法 数字两位 两位的连

田间机器人幼苗视觉检测与护苗施肥装置研究(大纲)

田间机器人幼苗视觉检测与护苗施肥装置研究 基于多光谱视觉与精准施肥的农业机器人系统设计 第一章 绪论 1.1 研究背景与意义 农业智能化需求&#xff1a; 传统幼苗检测依赖人工&#xff0c;效率低且易遗漏弱苗/病苗施肥不精准导致资源浪费和环境污染 技术挑战&#xff1a;…

Debian12生产环境配置笔记

在 Debian 12 上进行生产环境配置的详细步骤&#xff0c;涵盖软件更新、基础软件安装、Docker 及 Redis 部署&#xff0c;以及 Nginx 配置多个虚拟主机等内容。所有命令均以 root 用户身份执行&#xff0c;无需添加 sudo 1. 更新软件 首先&#xff0c;确保系统上的所有软件包…

HAL库编程知识点---Can.c和Driver_can.c分层开发

在一个工程中&#xff0c;通常会把对CAN外设的操作分成底层和上层两个部分&#xff0c;从而提高代码的模块化和可维护性。一般来说&#xff1a; can.c 通常由硬件抽象层&#xff08;HAL&#xff09;或者自动生成工具&#xff08;如 CubeMX&#xff09;提供或生成。主要负责CAN硬…

7. 【Vue实战--孢子记账--Web 版开发】-- 收支分类设置

本篇文章我们一起来实现收支分类功能。收支分类和前篇文章的主币种设置界面大体类似。我们将详细介绍如何创建和管理不同的收支分类&#xff0c;以便用户可以更好地组织和跟踪他们的财务状况。 一、功能 先来看一下原型界面&#xff0c;界面很简单&#xff0c;这里就不多讲解…