谈谈我对SOFA模块化的理解
今天我们谈谈SOFA模块化,首先看一段SOFA的介绍:
SOFABoot是蚂蚁金服开源的基于Spring Boot的研发框架,它在Spring Boot的基础上,提供了诸如 Readiness Check,类隔离,日志空间隔离等能力。在增强了Spring Boot的同时,SOFABoot提供了让用户可以在Spring Boot中非常方便地使用SOFA中间件的能力。
在接触SOFA的模块化概念之前,我对服务端开发的模块化认知停留在“模块化”这个层面,我通常会按照下图所示的结构组织自己负责的应用的代码。
在Spring体系中的模块(Module),就是通过不同的Spring上下文来管理各自模块中的bean,在开发和编译期实现模块化,但是在运行时整个应用还是在一个Spring上下文中,这些代码还都是被一个类加载器加载的。
在图1中,我在manager模块中定义的bean,在service中可以随时引用,而不需要关注这个引用是否合理;这样的开发模式在应用还小的时候没什么问题,不过,随着业务的发展和应用的升级,这些模块之间的引用关系会越来越复杂而无法管理(这时候应用也就成为了一个“大泥球”),当某一天需要对应用进行服务化拆分的时候,就需要花很大的精力去理清不同模块之间的耦合和引用关系。SOFA的模块化特性就是为了解决这个问题而出现的,这种特性可以强制开发者在增加两个模块之间的引用关系的时候进行仔细的设计和思考。
SOFA的模块化
SOFA的模块,是一种可运行的模块;普通的Spring项目中的模块,则是普通的Jar。一个完整的 SOFA模块和一个普通的Jar包有两点区别:
- SOFA模块包含一份
sofa-module.properties文件,这份文件里面定义了SOFA模块的名称以及模块之间的依赖关系。 - SOFA模块的
META-INF/spring目录下,可以放置任意多的Spring配置文件,SOFA会自动把它们作为本模块的Spring配置加载起来。
使用SOFA模块化特性后,两个模块之间的bean无法直接通信,需要使用SOFA的通信协议进行通信,SOFA支持两种通信协议:
- jvm调用,两个模块是在同一个JVM虚拟机中运行,无需经过网络调用。
- rpc调用,两个模块不是在同一个JVM虚拟机中运行,甚至不是在一台机器上,需要经过网络调用。
SOFA为开发人员提供了三种形式的发布和引用服务的方式:xml方式、注解方式、编程方式。我现在用的比较多的还是xml方式,原因在于SofaService和SofaReference都是只支持jvm服务的发布和引用,而xml方式则可以支持两种形式的调用。
SOFA模块化对开发模式的影响
SOFA提供的模块化解决方案,既实现了真正的、运行时的模块化,又没有过度引入OSGI的复杂度,是一种有效的折衷方案。接触SOFA到熟悉SOFA的过程对我的开发思路影响很大,但是在熟悉了SOFA的模块化思想之后,我发现这个特性对于我平常的开发工作有几个好处。
安全的近远端架构
为了降低服务端的压力,我们需要提供一个SDK供业务方使用,在之前Spring体系下,这种架构也是可以执行的,但是有个弊端——SDK中应用的类和JAR包对于业务方的应用来说也是可见的,在某些情况下会出现冲突或引入潜在的BUG。
使用SOFA的模块化特性,我们提供的近端包虽然还是跟业务方的应用共享一个JVM,但是在类加载器层面实现了隔离,对于业务方来说,他们只需要知道是使用了我们的哪些接口,而不需要关注我们这个SDK引入了多少三方JAR包。
更好的代码共享
利用SOFA模块化,要实现代码共享,可没有Spring体系下那么简单——直接引用给一个模块就可以。在SOFA中,要进行代码共享,通常有两种情况:(1)近远端代码共享(2)管理时和运行时代码共享。
以第(1)种情况为例,某个组件近远端都是一样的,为了避免代码重复,我们如何实现代码共享呢?我现在的做法是:在一个公共的test-core模块中定义需要共享的接口和实现类;这个test-core模块不能定义为SOFA的模块,只能定义为一个普通的JAR包;然后在需要使用该接口的SOFA模块(近端模块和远端模块)中,分别声明和引用那个共享的bean,示例图如下所示。
这里的重点在于:
- javaadu-core模块中是一个普通的JAR模块,只有接口的定义和实现,在这个模块中没有对bean的声明
- javaadu-remote模块中是一个SOFA模块,在这里引用了javaadu-core中的接口和实现,这里需要对bean进行声明(bean声明)和发布(sofa-service),当前应用的其他模块要想使用该接口,只需要引用javaadu-core和javaadu-remote,然后使用sofa-reference引用该接口就可以,这里一般是jvm调用;其他应用如果想使用该接口,并且没有近端需求的话,则需要引用javaadu-core和javaadu-remote,并使用sofa-reference引用。可以看出,SOFA模糊了跨应用调用和应用内调用的概念,模块化做得很彻底
- javaadu-client模块是一个SOFA模块,也是近端模块,在这里也需要自己定义和使用javaadu-core中的接口和实现。
总结
本文主要介绍了SOFA开发框架与Spring体系区别最明显的一个特性:SOFA模块化,通过每个模块一个Spring上下文的形式,实现了真正的运行时隔离。
基于我个人的使用经验,SOFA模块化对服务端开发的影响优大于劣:在维护代码中的过程中会仔细斟酌当前应用的模块依赖结构是否合理;可以更安全得提供SDK给业务方使用;在实现代码共享的时候,也需要仔细考虑哪些代码值得共享,哪些不需要。
参考资料
- Sofaboot-模块化开发概述
- 蚂蚁金服的业务系统模块化之模块化隔离方案
- 阿里巴巴Java开发手册(华山版).pdf
- JVM服务发布与引用
***
本号(javaadu)专注于后端技术、JVM问题排查和优化、Java面试题、个人成长和自我管理等主题,为读者提供一线开发者的工作和成长经验,期待你能在这里有所收获。
谈谈我对SOFA模块化的理解的更多相关文章
- 谈谈你对 Java 平台的理解
声明 本篇所涉及的提问,正文的知识点,全都来自于杨晓峰的<Java核心技术36讲>,当然,我并不会全文照搬过来,毕竟这是付费的课程,应该会涉及到侵权之类的问题. 所以,本篇正文中的知识点, ...
- java面试题(杨晓峰)---第一讲谈谈你对java平台的理解
本人总结: 面向对象(封装,继承,多态) 平台无关性(jvm运行,class文件) 语言(泛型,lambda) 类库(集合,并发,网络,io/nio) jre(java运行环境,JVM,类库) JDK ...
- 谈谈你对java平台的理解?
问题:谈谈你对java平台的理解?java是解释执行,这句话对吗? 典型回答:java本身是一种面向对象的语言,具有很好的跨平台的能力,能够做到“write once ,run anywhere”.另 ...
- Java核心-01 谈谈你对Java平台的理解
今天我要问你的问题是,谈谈你对 Java 平台的理解?“Java 是解释执行”,这句话正确吗? 典型回答 Java本身是一种面向对象的语言,最显著的特性有两个.一是所谓的“书写一次,到处运行”,能够非 ...
- 谈谈你对 Struts 2 的理解
谈谈你对Struts的理解. struts是一个按MVC模式设计的Web层框架,其实它就是一个大大的servlet,这个Servlet名为ActionServlet,或是ActionServlet的子 ...
- seajs模块化作用理解(一句话)
seajs是js模块化的工具,主要大文件js不方便其他人理解,加载也较慢,seajs把各个功能模块分开,方便平行化开发,同时易于修改和理解,不用重复写功能需要时就应用 (有什么错误,请指正,缺少多谢补 ...
- 谈谈我对C# 多态的理解
面向对象三要素:封装.继承.多态. 封装和继承,这两个比较好理解,但要理解多态的话,可就稍微有点难度了.今天,我们就来讲讲多态的理解. 我们应该经常会看到面试题目:请谈谈对多态的理解. 其实呢,多态非 ...
- 谈谈对HTML语义化的理解
什么是HTML语义化? HTML标签可以分为有语义的标签,和无语义的标签.比如table表示表格,form表示表单,a标签表示超链接,strong标签表强调.无语义标签典型的有<div>, ...
- 谈谈你对this对象的理解
理解: 1.this是js 的一个关键字,随着函数的使用场合的不同,this 的值会发生变化. 2.一个总原则:即this指的是调用函数的那个对象. 3.一般情况下,this 是全局对象,可以作为方法 ...
随机推荐
- SpringBoot入门(一):从HelloWorld开始
从0开始创建springBoot项目,话不多说,跟着我一步一步来就行了. 1.新建项目 1) 创建新项目,选择project, 点点点就好了 2) Spring Initializr——>选择 ...
- wp伪静态网页打开慢之提速方案1s内打开 wp的静态化插件测试
自上篇文章,我做了伪静态话.可是伪静态访问还是php动态页面,还需要服务端分析如何处理,访问页面时会发现有一个漫长的等待响应的时间.这是打开速度在4s左右.而静态页面则是直接打开,不需要服务器操作,不 ...
- Java IO 为什么我们需要缓冲区
在执行IO操作我们通常会设置一个字节数组作为缓冲区用来写/读数据,一般情况下一个合理大小的缓冲区是有利于提升性能的,但是有一个问题一直困扰着我,为什么缓冲区可以提升IO操作的性能? 经查阅资料之后,总 ...
- UltraEdit不自动生成保存备份文件(.bak)
UltraEdit修改文件或格式化文件保存后会生成烦人的.bak文件. 去掉该功能办法如下: 高级 -> 配置 -> 文件处理 -> 备份 “保存时备份文件”选择“不备份” (Adv ...
- CMS简单内容管理系统
架构 NewsDaoSQLServerImpl public class NewsDaoSQLServerImpl extends BaseDao implements NewsDao { publi ...
- IDEA:No SLF4J providers were found.
如果您是用IDEA 的 maven 写的 将slf4j的导入包 更改 为下列代码 <dependency> <groupId>org.slf4j</groupId> ...
- codeforces 339 D.Xenia and Bit Operations(线段树)
这个题目属于线段树的点更新区间查询,而且查的是整个区间,其实不用写query()函数,只需要输出根节点保存的值就可以了. 题意: 输入n,m表示有2^n个数和m个更新,每次更新只把p位置的值改成b,然 ...
- go 学习笔记之走进Goland编辑器
工欲善其事必先利其器,命令行工具虽然能够在一定程度上满足基本操作的需求,但实际工作中总不能一直使用命令行工具进行编码操作吧? 学习 Go 语言同样如此,为此需要寻找一个强大的 IDE 集成环境帮助我们 ...
- 手摸手,带你用vue实现后台管理权限系统及顶栏三级菜单显示
手摸手,带你用vue实现后台管理权限系统及顶栏三级菜单显示 效果演示地址 项目demo展示 重要功能总结 权限功能的实现 权限路由思路: 根据用户登录的roles信息与路由中配置的roles信息进行比 ...
- 为什么建立数据仓库需要使用ETL工具?
在做项目时是不是时常让客户有这样的困扰: 1.开发时间太长 2.花费太多 3.需要太多资源 4.集成多个事务系统数据总是需要大量人力成本 5.找不到合适的技能和经验的人 6.一旦建立,数据仓库无法足够 ...