蚂蚁SOFA系列(1) - 聊聊SOFA的模块化
作者: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模块化的实现原理,将另起一文,欢迎关注下方公众号,更多思考,与你分享。
近期文章:
蚂蚁SOFA系列(1) - 聊聊SOFA的模块化的更多相关文章
- 蚂蚁SOFA系列(2) - SOFABoot的Readiness健康检查机制
作者:404,公众号404P,转载请注明出处. 前言 SOFABoot是蚂蚁金服的开源框架,在原有Spring Boot的基础上增强了不少能力,例如Readiness Check,类隔离,日志空间隔离 ...
- Java9系列第8篇-Module模块化编程
我计划在后续的一段时间内,写一系列关于java 9的文章,虽然java 9 不像Java 8或者Java 11那样的核心java版本,但是还是有很多的特性值得关注.期待您能关注我,我将把java 9 ...
- 深入浅出百度地图API开发系列(3):模块化设计
在前面两张简单介绍了百度地图API的基础知识和使用之后,我们来分析一下百度地图API的基本架构,了解一下基本架构可以帮助我们更清晰的了解API的功能和调用过程,也就可以帮助我们在实际开发中可以更方便的 ...
- Python 单元测试框架系列:聊聊 Python 的单元测试框架(一):unittest
作者:HelloGitHub-Prodesire HelloGitHub 的<讲解开源项目>系列,项目地址:https://github.com/HelloGitHub-Team/Arti ...
- 聊聊MVC和模块化以及MVVM和组件化
原文链接 小寒的博客,带你理解更深的世界 面向对象,模块化和MVC 面向对象是指把写程序映射到现实生活,从而一来逻辑性更强,更容易写好代码,二来代码很贴切,通俗易懂,更被人理解,三来更加容易拓展和管理 ...
- 模块化系列教程 | 阿里JarsLink1.0模块化场景实战Demo
场景实战Demo使用指引 Quickstart 快速开始 Demo说明 模块说明 使用说明 情景一环境部署 工作原理 情景二环境部署 工作原理 场景实战Demo使用指引 个人之前学习过程中对JarsL ...
- C#系列之聊聊.Net Core的InMemoryCache
作者:暴王 个人博客:http://www.boydwang.com/2017/12/net-core-in-memory-cache/ 这两天在看.net core的in memory cache, ...
- 蚂蚁金服研发的金融级分布式中间件SOFA背后的故事
导读:GIAC大会期间,蚂蚁金服杨冰,黄挺等讲师面向华南技术社区做了<数字金融时代的云原生架构转型路径>和<从传统服务化走向Service Mesh>等演讲,就此机会,高可用架 ...
- Train-Alypay-Cloud:分布式微服务中间件sofa 开发培训(第二次)
ylbtech-Train-Alypay-Cloud:分布式微服务中间件sofa 开发培训(第二次) 1.返回顶部 1. 这是本次培训的内容,望各位提前配好环境.工具.2.6-2.7 我们在环球金融8 ...
随机推荐
- EditText 使用详解
极力推荐文章:欢迎收藏 Android 干货分享 本篇文章主要介绍 Android 开发中的部分知识点,通过阅读本篇文章,您将收获以下内容: 一.EditText 继承关系 二.EditText 常用 ...
- 【Java例题】2.4求函数
4.输入x,编程试求函数 y=sin(x^2)/(1-cosx)的值. 这里的"^"表示乘方. package study; import java.util.Scanner; p ...
- Java——异常处理
1.java提供的异常不可能预见所有的问题,所以需要自己定义异常类,必须从已有的异常类继承,最好选择意思相近的异常类继承. class MyException extends Exception{} ...
- android ——Toolbar
Toolbar是我看material design内容的第一个 官方文档:https://developer.android.com/reference/android/support/v7/widg ...
- 一文了解:Redis的AOF持久化
Redis的AOF持久化 每当Redis-Server接收到写数据时,就把命令以文本形式追加到AOF文件里,当重启Redis服务时,AOF文件里的命令会被重新执行一次,重新恢复数据.当AOF过大时将重 ...
- Logback配置文件这么写,TPS提高10倍
通过阅读本篇文章将了解到 1.日志输出到文件并根据LEVEL级别将日志分类保存到不同文件 2.通过异步输出日志减少磁盘IO提高性能 3.异步输出日志的原理 配置文件logback-spring.xml ...
- CodeForces 15D Map
洛谷题目页面传送门 & CodeForces题目页面传送门 题意见洛谷里的翻译.(注意翻译里有错误,应该是优先选上面的矩阵,在同一行的优先选左边的矩阵) 这题一看就会做啊 (以下设大矩阵是\( ...
- java高并发系列 - 第25天:掌握JUC中的阻塞队列
这是java高并发系列第25篇文章. 环境:jdk1.8. 本文内容 掌握Queue.BlockingQueue接口中常用的方法 介绍6中阻塞队列,及相关场景示例 重点掌握4种常用的阻塞队列 Queu ...
- 集合中Iterator迭代器的使用以及实现原理。
collection集合元素通用的获取方式,在取之前先要判断集合中有没有元素,如果有就把这个元素取出来,继续在判断,如果还有就再取出来,一直把集合中的元素全取出来,这种去出方式叫做迭代. 迭代器的作用 ...
- 因为配置了Always-On导致的无法Drop Login...
一个sysadmin离职了,但是因为之前是他配置的Always-on,所以试图Drop他的login就会失败,原因是这个login会赋予一个叫做“Hadr_endpoint”的endpoint权限,并 ...