今天我们谈谈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. Sofaboot-模块化开发概述
  2. 蚂蚁金服的业务系统模块化之模块化隔离方案
  3. 阿里巴巴Java开发手册(华山版).pdf
  4. JVM服务发布与引用
    ***
    本号(javaadu)专注于后端技术、JVM问题排查和优化、Java面试题、个人成长和自我管理等主题,为读者提供一线开发者的工作和成长经验,期待你能在这里有所收获。

谈谈我对SOFA模块化的理解的更多相关文章

  1. 谈谈你对 Java 平台的理解

    声明 本篇所涉及的提问,正文的知识点,全都来自于杨晓峰的<Java核心技术36讲>,当然,我并不会全文照搬过来,毕竟这是付费的课程,应该会涉及到侵权之类的问题. 所以,本篇正文中的知识点, ...

  2. java面试题(杨晓峰)---第一讲谈谈你对java平台的理解

    本人总结: 面向对象(封装,继承,多态) 平台无关性(jvm运行,class文件) 语言(泛型,lambda) 类库(集合,并发,网络,io/nio) jre(java运行环境,JVM,类库) JDK ...

  3. 谈谈你对java平台的理解?

    问题:谈谈你对java平台的理解?java是解释执行,这句话对吗? 典型回答:java本身是一种面向对象的语言,具有很好的跨平台的能力,能够做到“write once ,run anywhere”.另 ...

  4. Java核心-01 谈谈你对Java平台的理解

    今天我要问你的问题是,谈谈你对 Java 平台的理解?“Java 是解释执行”,这句话正确吗? 典型回答 Java本身是一种面向对象的语言,最显著的特性有两个.一是所谓的“书写一次,到处运行”,能够非 ...

  5. 谈谈你对 Struts 2 的理解

    谈谈你对Struts的理解. struts是一个按MVC模式设计的Web层框架,其实它就是一个大大的servlet,这个Servlet名为ActionServlet,或是ActionServlet的子 ...

  6. seajs模块化作用理解(一句话)

    seajs是js模块化的工具,主要大文件js不方便其他人理解,加载也较慢,seajs把各个功能模块分开,方便平行化开发,同时易于修改和理解,不用重复写功能需要时就应用 (有什么错误,请指正,缺少多谢补 ...

  7. 谈谈我对C# 多态的理解

    面向对象三要素:封装.继承.多态. 封装和继承,这两个比较好理解,但要理解多态的话,可就稍微有点难度了.今天,我们就来讲讲多态的理解. 我们应该经常会看到面试题目:请谈谈对多态的理解. 其实呢,多态非 ...

  8. 谈谈对HTML语义化的理解

    什么是HTML语义化? HTML标签可以分为有语义的标签,和无语义的标签.比如table表示表格,form表示表单,a标签表示超链接,strong标签表强调.无语义标签典型的有<div>, ...

  9. 谈谈你对this对象的理解

    理解: 1.this是js 的一个关键字,随着函数的使用场合的不同,this 的值会发生变化. 2.一个总原则:即this指的是调用函数的那个对象. 3.一般情况下,this 是全局对象,可以作为方法 ...

随机推荐

  1. 【数据库】postgresql数据库创建自增序列id的注意事项

    1.创建一张表 CREATE TABLE "public"."tt" ( "name" varchar(128), "status ...

  2. Android的简述4

    NoteEditor深入分析 首先来弄清楚“日志编辑“的状态转换,通过上篇文章的方法来做下面这样一个实验,首先进入“日志编辑“时会触发onCreate和onResume,然后用户通过Option Me ...

  3. C语言编程入门之--第三章编写第一个C语言程序

    第三章 编写第一个C语言程序 导读:一般学一门计算机语言的第一堂上机课(“上机”顾名思义,上了计算机),就是往屏幕输出“hello world”,本章也不例外. 1.1 Hello,World! 这一 ...

  4. 关于STM32F103+ESP8266+阿里云过程之设备状态更新至阿里云(三)

    设备与阿里云完成发布订阅的功能,接下来就是将设备状态如温湿度,PM2.5值上报更新至阿里云. 1.查看Topic. 在阿里云平台上 设备->Topic列表中查看.在产品中也可以看到对应的Topi ...

  5. “$Bitmap 有标记已使用的未用簇”

    前几天在电脑上用 DiskGenius 给移动硬盘分区的时候出现了这个错误,如下图所示: 解决方法: 在 cmd 命令行窗口中输入如下代码: chkdsk /f /x c: PS: 其中 " ...

  6. 【iOS】Receiver type 'XXX' for instance message is a forward declaration

    今天遇到这个错误.刚开始字体太大,没显示全,后来调小字体之后看到了完整提示信息: 之后就忽然想起没引入相关的类,添加 #import "RDVTabBarItem.h" 就行了.

  7. 精准营销、批量提取QQ群成员号码

    有时我们在做精准营销时,需要从社群里提取群成员的QQ号,群发邮件,常规的做法是手工一个个复制粘贴,这样的效率无疑是很低的,下面我来分享一个批量获取社群的QQ号方法. 需要具备以下工具: 1.大量精准Q ...

  8. 从动态代理到Spring AOP(中)

    一.前言 上一章节主要介绍了JDK动态代理和CGLIB动态代理:https://www.cnblogs.com/GrimMjx/p/11194283.html 这一章主要结合我们之前学习的动态代理的基 ...

  9. Git应用之eclipse解决冲突代码

    最近上班公司框架换成了微服务下面是eclipse 对代码进行管理 1.冲突代码 如果两个人在一个项目上同一文件上更改代码就会出现冲突现象 先用NewFile.jsp  文件做演示 打开eclipse从 ...

  10. javaweb入门-----jsp概念

    jsp是什么? JSP:Java Server Pages java服务器端页面 *可以理解为 一个特殊的页面,其中既可以直接定义html标签,又可以定义java代码 *用于简化书写 <% %& ...