本文阅读时间大约7分钟。

今天我们谈谈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给业务方使用;在实现代码共享的时候,也需要仔细考虑哪些代码值得共享,哪些不需要。

参考资料

  1. https://www.sofastack.tech/projects/sofa-boot/modular-development/

  2. https://www.sofastack.tech/blog/sofastack-modular-isolation/

  3. 阿里巴巴Java开发手册(华山版).pdf

  4. https://www.sofastack.tech/projects/sofa-boot/module-service/

下方查看历史文章

JVM调优实战:G1中的to-space exhausted问题

Java 8的这个新特性,你用了吗?

【译】深入理解G1的GC日志(一)

使用Optional摆脱NPE的折磨

本号专注于后端技术、JVM问题排查和优化、Java面试题、个人成长和自我管理等主题,为读者提供一线开发者的工作和成长经验,期待你能在这里有所收获。

让我知道你“在看”

通过SOFA看Java服务端如何实现运行时的模块化的更多相关文章

  1. Flex通信-Java服务端通信实例

    转自:http://blessht.iteye.com/blog/1132934Flex与Java通信的方式有很多种,比较常用的有以下方式: WebService:一种跨语言的在线服务,只要用特定语言 ...

  2. thrift例子:python客户端/java服务端

    java服务端的代码请看上文. 1.说明: 这两篇文章其实解决的问题是,当使用python去访问大数据线上集群的时候,遇到两个问题: 1)python-hadoop和python-hive相关包链接不 ...

  3. Java 服务端监控方案(四. Java 篇)

    http://jerrypeng.me/2014/08/08/server-side-java-monitoring-java/ 这个漫长的系列文章今天要迎来最后一篇了,也是真正与 Java 有关的部 ...

  4. Java 服务端入门和进阶指南

    作者:谢龙 链接:https://www.zhihu.com/question/29581524/answer/44872235 来源:知乎 著作权归作者所有,转载请联系作者获得授权. 现在互联网上资 ...

  5. java服务端集成极光消息推送--详细开发步骤

    1.极光推送账号准备 要使用极光消息推送必须先在官方网站上注册账号,并添加应用. 产品介绍:https://docs.jiguang.cn/jpush/guideline/intro/ 注册开发者账号 ...

  6. 那些年,我们见过的 Java 服务端乱象

    导读 查尔斯·狄更斯在<双城记>中写道:“这是一个最好的时代,也是一个最坏的时代.” 移动互联网的快速发展,出现了许多新机遇,很多创业者伺机而动:随着行业竞争加剧,互联网红利逐渐消失,很多 ...

  7. 那些年,我们见过的 Java 服务端“问题”

    导读 明代著名的心学集大成者王阳明先生在<传习录>中有云: 道无精粗,人之所见有精粗.如这一间房,人初进来,只见一个大规模如此.处久,便柱壁之类,一一看得明白.再久,如柱上有些文藻,细细都 ...

  8. 那些年,我们见过的Java服务端乱象

    导读 查尔斯·狄更斯在<双城记>中写道:“这是一个最好的时代,也是一个最坏的时代.”移动互联网的快速发展,出现了许多新机遇,很多创业者伺机而动:随着行业竞争加剧,互联网红利逐渐消失,很多创 ...

  9. 俯瞰 Java 服务端开发

    原文首发于 github ,欢迎 star . Java 服务端开发是一个非常宽广的领域,要概括其全貌,即使是几本书也讲不完,该文将会提到许多的技术及工具,但不会深入去讲解,旨在以一个俯瞰的视角去探寻 ...

随机推荐

  1. django之分页器、多对多关系、form校验组件

    批量插入数据 bulk_create # 1.往书籍表中插入数据 1000 # for i in range(1000): # 这种插入方式 效率极低 # models.Book.objects.cr ...

  2. 大宗商品市场的未来王者 | 现货贸易商PK期货风险管理子公司

    https://mp.weixin.qq.com/s/z-kkeIor6vDb9Oer73Ct6w 大宗商品市场卧虎藏龙,参与者众多,然而能称之为王者的却寥寥无几. 在国外,以嘉能可.托克.摩科瑞为代 ...

  3. ASP.NET Core 中的 依赖注入介绍

    ASP.NET Core 依赖注入 HomeController public class HomeController : Controller { private IStudentReposito ...

  4. 【HDU6327】Random Sequence(记忆化搜索)

    点此看题面 大致题意: 给你两个序列\(a,v\),其中\(a\)数组由\(0\sim m\)组成.随机用\(1\sim m\)中的一个数替换\(a\)中的\(0\),求\(\sum_{i=1}^{n ...

  5. [清华集训2017]小 Y 和地铁(神奇思路,搜索,剪枝,树状数组)

    世界上最不缺的就是好题. 首先考虑暴搜.(还有什么题是从这东西推到正解的……) 首先单独一个换乘站明显没用,只用考虑一对对的换乘站. 那么有八种情况:(从题解偷图)         然后大力枚举每个换 ...

  6. [LeetCode] 402. Remove K Digits 去掉K位数字

    Given a non-negative integer num represented as a string, remove k digits from the number so that th ...

  7. [LeetCode] 145. Binary Tree Postorder Traversal 二叉树的后序遍历

    Given a binary tree, return the postorder traversal of its nodes' values. For example: Given binary ...

  8. 使用PAC文件来管理代理连接

    生成PAC文件 谷歌浏览器插件商店安装SwitchyOmega,找到立即更新模式,然后导出PAC文件 使用PAC文件 pac采用js编写 Windows Windows上面使用PAC文件很简单,新建一 ...

  9. NOIP 2018 简要题解

    从这里开始 Day 1 Problem A 考虑贪心地选取极大非 0 段减少. 如果两次操作有交,并且不是包含关系,那么把其中一次操作的,但另一次没有操作的移过去,然后就变成了上面那个贪心了. Cod ...

  10. luogu P5605 小 A 与两位神仙 - 原根

    题目传送门 传送门 Subtask 1 直接模拟. Subtask 2 BSGS算法模板. Subtask 3 考虑模 $m$ 的任意一个原根 $g$. 假设 $g^{ra} \equiv x \pm ...