作者:404,转载请注明出处。欢迎关注公众号:404P。

SOFA是蚂蚁自研的一套金融级分布式中间件,目前正在逐步向业界开源。SOFA的全称有两个,最早是Service Oriented Fabric Architecture,即面向服务的架构。随着2018年的开源,其全称改为Scalable Open Financial Architecture,即可扩展的开源金融架构。

SOFA技术栈包含了微服务架构体系的各类组件,主要包括RPC框架,服务注册中心,分布式链路追踪,Metrics监控度量等。

本文我们来聊聊SOFA的模块化。

一 什么是模块化

模块化在计算机领域是经常讨论的话题,在学校学编程语言的时候,教科书上说程序设计要遵循模块化原则。

模块化程序设计是指在进行程序设计时将一个大程序按照功能划分为若干小程序模块,每个小程序模块完成一个确定的功能,并在这些模块之间建立必要的联系,通过模块的互相协作完成整个功能的程序设计方法。

上面这段话引自百度百科,其实精炼下就是:高内聚和低耦合

二 模块化思想演变

1 代码设计模块化

最早学编程的时候,实现一个功能,所有逻辑放到一个main函数里去,后来发现理不清了,就把main里面的逻辑抽成几个函数。这是模块化吗?是。这个模块化是最基本的代码设计能力,增强代码的可读性、可维护性和可扩展性。如下图,计算成绩的时候,没有把所有逻辑放在A中,而是分在B1和B2中,单独计算,最后A调用B1、B2来实现。

在这种简单的程序设计中,往往更注重逻辑的内聚性,只要内聚做好了,往往就是低耦合的。

2 业务领域模块化

在真实做一些项目的时候,业务系统比较复杂,要实现的功能很多。这个时候出现了横向和纵向的模块化设计。横向的就是分层设计,纵向的就是按照不通的业务领域来设计。

一个业务系统,横向的模块化切分主要分为三大层:Web层,Service层,DAL层。

在业务初期,功能往往都是写在一个业务系统的,比如订单模块Order、库存模块Stock。在maven中这些模就是不同的module,但运行都是在同一个JVM,同一个web容器中的。

这在种情况下,订单服务依赖于库存服务怎么办?订单模块的pom中引入库存模块的依赖。然后注入bean。

public class OrderService {
@Autowired
private StockService stockService;
}

这种横纵模块化思想随着业务的复杂开始进化了。订单、库存模块虽然在一个Service层,但属于明显不同的领域,已经被分成不同的模块了,具有很好的内聚性,而且要引用其它模块,必须引入pom依赖之后才能访问,具有不错的隔离型。

3 业务系统模块化的弊端

但是,这样设计的耦合性还是不够低,隔离性不够强。

程序员小胖:还不够强吗?订单模块和库存模块都在不同的module了,不费任何力气,就可以直接把源代码分成两个项目,由不同的团队来写了。

404P: 不够,现在的隔离性最多在开发层,能够相互隔离开发。运行时呢?

所有module的bean都在同一个spring context中,A模块可以任意引用B模块的bean,开发同学引入另一个module之后,不太清楚该module中哪些是对外提供的的接口,哪些bean是可以直接注入调用的,哪些Bean是内部Bean,不适合直接去注入的。

长期如此,一个模块的bean被不断地注入到另外一个模块被调用,那么其运行时的隔离性就差了。运行时没有做好隔离,是服务拆分的一大痛点。大概就是下图这个样子。

程序员小胖:请继续你的表演。

404P:随着业务的增长,必然会把Order和Stock拆分,成为不同的子业务系统。代码在不同的module,拆分开来很简单,但是拆分后两个业务系统是运行在不同的SpringContext中的。而bean的注入只在一个SpringContext有效,所以之前通过bean注入来实模块交互的地方需要梳理出来,变成系统之间的接口交互才能实现服务拆分。

程序员小胖:听你这么一说,有道理。模块化思想都是跟着架构思想走的啊。如果要考虑未来模块拆分成服务,就需要考虑好运行时隔离,也就是运行时的低耦合交互。

404P: 是的。看看SOFA怎么做的。

三 SOFA模块化

为了防止这种模块之间滥用bean注入来交互。SOFA启动后,会为每个moudule创建一个SpringContext,每个module运行在各自的SpringContext中。不同模块之间的bean无法直接引用,具备了较好的运行时隔离能力。

那么当Order模块想引用Stock模块的Bean,怎么办呢?

首先,需要Stock模块有发布对外的公共bean,通过如下声明式发布(也可以通过注解方式):

<sofa:service ref="stockBeanA" interface="com.alipay.sofa.StockBeanA"/>

那Order模块怎么引用Stock模块中的公开bean呢?通过如下声明方式引用:

<sofa:reference id="stockBeanA" interface="com.alipay.sofa.StockBeanA"/>

Stock模块的stockBeanA已经公开发布,并且Order模块已经引用,那么Order模块在编码的时候,就可以直接注入bean stockBeanA了。

这种方式,我们可以很清晰地看到一个模块公开了哪些服务,引用了哪些服务。模块之间的交互变得非常清晰。

四 SOFA模块拆分成微服务

当一个SOFA应用开始变得复杂,开发团队成员开始增多时,就需要进行服务化了。比如,Order模块和Stock模块,不再是运行在一个系统了,而是要变成Order系统和Stock系统了。这意味着这两个领域之间的交互从模块级别的交互上升到应用系统级别的交互了。

这种服务化拆分需要考虑两点:

(1)模块化的交互是在同一JVM内存中不同SpringContext之间的交互,拆分成两个应用系统后,应用系统之间交互必然是通过网络请求来交互,必然要考虑远程通信的问题。

(2)模块之间的服务发布和引用与应用系统之间的服务发布和引用是否有差异,需要改造?

SOFA考虑了以上两点,要将一个SOFA模块拆成微服务是非常便捷的。

Stock应用发布的时候,如下:

<sofa:service ref="stockBeanA" interface="com.alipay.sofa.StockBeanA">
<sofa:binding.bolt/>
</sofa:service>

Order应用引用Stock的服务时,如下

<sofa:reference id="stockBeanA" interface="com.alipay.sofa.StockBeanA">
<sofa:binding.bolt/>
</sofa:reference>

可以看出,就是添加了个属性 ,

<sofa:binding.bolt/>

表示服务之间的交互是通过sofa bolt远程调用框架来完成,发布和引用方式几乎没有变化。这种简易的服务化拆分,为蚂蚁架构在服务化演进的过程中带来了很大的便利。

五 结语

随着问题域的复杂性越来越高,模块之间的隔离边界也有更高的要求,本文从简单的例子,逐渐演变到服务拆分,从而引出SOFA的模块化。SOFA基于SpringContext作为模块隔离边界,充分降低了模块交互的耦合性,同时也为后续服务拆分提供了便利。

关于SOFA模块化的实现原理,将另起一文,欢迎关注下方公众号,更多思考,与你分享。


近期文章:

分布式幂等问题解决方案三部曲

Java跨平台?慎用这些有平台差异性的方法!

蚂蚁SOFA系列(1) - 聊聊SOFA的模块化的更多相关文章

  1. 蚂蚁SOFA系列(2) - SOFABoot的Readiness健康检查机制

    作者:404,公众号404P,转载请注明出处. 前言 SOFABoot是蚂蚁金服的开源框架,在原有Spring Boot的基础上增强了不少能力,例如Readiness Check,类隔离,日志空间隔离 ...

  2. Java9系列第8篇-Module模块化编程

    我计划在后续的一段时间内,写一系列关于java 9的文章,虽然java 9 不像Java 8或者Java 11那样的核心java版本,但是还是有很多的特性值得关注.期待您能关注我,我将把java 9 ...

  3. 深入浅出百度地图API开发系列(3):模块化设计

    在前面两张简单介绍了百度地图API的基础知识和使用之后,我们来分析一下百度地图API的基本架构,了解一下基本架构可以帮助我们更清晰的了解API的功能和调用过程,也就可以帮助我们在实际开发中可以更方便的 ...

  4. Python 单元测试框架系列:聊聊 Python 的单元测试框架(一):unittest

    作者:HelloGitHub-Prodesire HelloGitHub 的<讲解开源项目>系列,项目地址:https://github.com/HelloGitHub-Team/Arti ...

  5. 聊聊MVC和模块化以及MVVM和组件化

    原文链接 小寒的博客,带你理解更深的世界 面向对象,模块化和MVC 面向对象是指把写程序映射到现实生活,从而一来逻辑性更强,更容易写好代码,二来代码很贴切,通俗易懂,更被人理解,三来更加容易拓展和管理 ...

  6. 模块化系列教程 | 阿里JarsLink1.0模块化场景实战Demo

    场景实战Demo使用指引 Quickstart 快速开始 Demo说明 模块说明 使用说明 情景一环境部署 工作原理 情景二环境部署 工作原理 场景实战Demo使用指引 个人之前学习过程中对JarsL ...

  7. C#系列之聊聊.Net Core的InMemoryCache

    作者:暴王 个人博客:http://www.boydwang.com/2017/12/net-core-in-memory-cache/ 这两天在看.net core的in memory cache, ...

  8. 蚂蚁金服研发的金融级分布式中间件SOFA背后的故事

    导读:GIAC大会期间,蚂蚁金服杨冰,黄挺等讲师面向华南技术社区做了<数字金融时代的云原生架构转型路径>和<从传统服务化走向Service Mesh>等演讲,就此机会,高可用架 ...

  9. Train-Alypay-Cloud:分布式微服务中间件sofa 开发培训(第二次)

    ylbtech-Train-Alypay-Cloud:分布式微服务中间件sofa 开发培训(第二次) 1.返回顶部 1. 这是本次培训的内容,望各位提前配好环境.工具.2.6-2.7 我们在环球金融8 ...

随机推荐

  1. 大型系列课程之-七夕告白之旅Electron篇

    上一篇分享了一下vbs的撩妹攻略,但细心的兄弟会发现,这种脚本式的攻城方案并不得心应手,有很多妹子害怕是病毒根本不敢点击,而且这个脚本界面风格也不漂亮,不能轻易打动妹子的心,怎么破,小编这次在为各位老 ...

  2. JavaScript数据结构——栈的实现与应用

    在计算机编程中,栈是一种很常见的数据结构,它遵从后进先出(LIFO——Last In First Out)原则,新添加或待删除的元素保存在栈的同一端,称作栈顶,另一端称作栈底.在栈中,新元素总是靠近栈 ...

  3. 配置VNC并远程控制服务器(电脑)

    先象征性介绍一下: VNC (Virtual Network Console)是虚拟网络控制台的缩写, 它是一款基于 UNIX 和 Linux 操作系统的优秀.免费.开源的远程控制工具软件. 然后开始 ...

  4. (数据科学学习手札66)在ubuntu服务器上部署shiny

    一.简介 shiny是R中专门用于开发轻量级web应用的框架,在本地写一个shiny应用并调用非常方便,但如果你希望你的shiny应用能够以远程的方式提供给更多人来使用,就需要将写好的shiny应用部 ...

  5. 如何编写一个WebPack的插件原理及实践

    _ 阅读目录 一:webpack插件的基本原理 二:理解 Compiler对象 和 Compilation 对象 三:插件中常用的API 四:编写插件实战 回到顶部 一:webpack插件的基本原理 ...

  6. Spring1

    一.Spring是什么?有什么用? Spring的适用环境是这样的,假设现在有一个类port,它将提供一个返回消息的功能,代码如下: public class port { private weibo ...

  7. bootstrape select使用小结

    看看上面的效果是bootstrape使用的效果.虽然不是很好看,但是符合bootstrape的风格.来看看普通的select的样式 bootstrape下的select和普通select在bootst ...

  8. Java学习|String,StringBuffer,StringBuilder?

    1 String   (1) String的创建机理 由于String在Java世界中使用过于频繁,Java为了避免在一个系统中产生大量的String对象,引入了字符串常量池.其运行机制是:创建一个字 ...

  9. linuxdeploy安装报错

    报错内容:checking installation path…fail(检查安装路径) 处理方法:安装在手机自带的存储空间中,则在路径开头加上${ENV_DIR},安装在sdcard中,加上${EX ...

  10. Springboot源码分析之AbstractAdvisorAutoProxyCreator

    摘要: Spring的代理在上层中主要分为ProxyCreatorSupport和ProxyProcessorSupport,前者是基于代理工厂,后者是基于后置处理器,也可以认为后置就是自动代理器.当 ...