导读
经典单体分层架构
-
展现层:负责给最终用户展现信息,并接受用户的输入触发系统的业务逻辑。用户可以是使用系统的人,也可以是其他软件系统。
-
业务层:关注系统业务逻辑的实现
-
持久层:负责数据的存取
-
数据存储层:底层的数据存储设施
图1.经典的四层单体分层架构示意
-
层间的依赖关系由上到下逐层向下直接依赖,每层都是关闭状态,请求的数据流向从上到下,必须严格通过每个分层进行流转,而不能进行穿透调用。
-
关注点隔离:通过分层将系统的关注点进行垂直分配,每层只关注自身层边界内的职责,层间职责相互独立不存在交叉。比如业务层负责处理系统的核心业务逻辑,而持久层则关注于对数据的存取。
-
分层模型比较简单,理解和实现成本低
-
开放人员接受度和熟悉程度高,认知和学习成本低
-
层间数据效率问题: 由于层间调用关系的依赖约束,层间的数据流转需要付出额外成本
-
业务层服务能力的复用性:业务层中处于对等地位的组件或模块之间存在共享服务的诉求
-
引入通用服务层提供通用服务,提高复用性
-
通用服务层是开放层,允许调用链路穿透,业务层可以按需直接访问更下层的持久层
-
引入中间层降低了数据传输效率,提高了开发实现成本
-
有造成系统混乱度提升的风险:由于通用服务层的开放性导致业务层可以穿透调用。但这种是否需要进行穿透的场景无法形成统一的判定原则,往往依赖于实现人员的个人经验进行权衡,同一个业务场景由不同的开发人员实现可能会有不同的判定结果(在四层架构中如果放开层间调用约束也会存在该问题)。随着业务需求迭代,系统的依赖关系一定会日趋增加,最终形成复杂的调用关系,也导致系统复杂性上升,增加团队成员的认知成本。
单体分层架构的共性问题探讨
-
分层对系统复杂度和效率的影响
-
变化真的能完全隔离吗?
-
问题域与解决方案的隔离
图4.
-
其一:如何判定是否要跨层调用很难形成统一的严格判定标准,只能进行粗粒度划分。因此,在实现过程中会有不同的判定结果,系统的调用关系会随着代码规模增长而日趋复杂。当然,团队可以加强代码评审的粒度,每次评审基于是否穿透调用进行讨论、判断并达成一致。但实际经验是,由于人为因素,靠严格的代码评审并不能保证决策的一致性。
-
其二:如果允许跨层调用,则意味着 “模型” 的穿透,低层的模型会直接暴露在更上层,这与我们追求的组件内聚性和模型的封装性存在冲突
注:层间的依赖约束是一种架构决策,可以考虑通过自动化单元测试机制进行保证,具体可参考:
《基于ArchUnit守护系统架构》
-
你真的会替换数据库吗?你真的会替换ORM框架吗?有可能,但概率非常低,大部分系统并不会发生这种场景。
-
发生替换就真的能隔离吗?如果你的层间不是依赖于抽象,而是依赖于具体,那么隔离也无从谈起。
-
即使层间依赖于抽象,变化就真的隔离了吗?实现发生变化的直接结果就是依赖方需要引用新的实现,这种变化也同样会影响到上层。只不过是这种变化可能交由IOC容器了
-
如果是展现层需要增加一个新的字段,而当前数据库模型中没有?
-
如果是数据库中需要增加一个新的字段,而展现层和业务逻辑层不关心?
-
如果是......
分层可以控制变化在系统内的传播,由于变化场景的多样化,分层不能完全的隔离变化。
图5.
-
OrderConroller:Spring技术栈下的系统访问的Rest接口
-
OrderService/OrderServiceImpl:订单的核心业务逻辑实现服务,实现诸如下单、取消订单等逻辑
-
OrderDAO/OrdeDAOImpl:订单数据的存取
图6.在经典的分层单体架构风格中,典型的实现示意
-
首先,在工程顶层最先看到的是技术视角的Module(Maven Module):web、service 、dao
-
然后,需要在各层导航才能一窥其全貌
实现要反应抽象,组件化思维本质上一种模块化思维,通过内聚性和封装性,将问题空间进行拆分成子空间,分而治之。对外通过接口提供组件能力,屏蔽内部的复杂性。接口契约的大小粒度需要权衡,粒度越小,能力提供越约聚焦,理解和接入成本越低,但通用性越差。接口契约粒度越大,则通用性越强,但理解和接入复杂性越高。
图7.
将组件化思维应用于单体分层架构,引申出模块化单体架构风格。应用架构按照问题域进行模块化组织,而非基于技术关注点进行拆分。组件内部遵循内聚性原则,其内包含了实现组件能力所需要的各个元素及交互关系。组件之间通过统一的、合适粒度的接口契约进行交互,不直接依赖于组件的内部能力或模型。同时,组织良好的模块化单体应用架构也是进行微服务拆分的重要保证。如果你无法在单体架构中进行优雅的模块化组织,又何谈合理的微服务拆分呢?
03
结语
单体分层架构风格是分层思想在单体架构中的应用,其关注于技术视角的职责分层。同时,基于不同层变化速率的不同,在一定程度上控制变化在系统内的传播,有助于提升系统的稳定性。但这种技术视角而非业务视角的关注点隔离,导致了问题域与工程实现之间的Gap,这种割裂会导致系统认知复杂度的提升。将组件化思维应用于单体分层架构,模块化单体技术视角的分层拉回至业务域视角的模块化,一定程度上降低业务与工程实现间的隔离。良好的模块化是单体走向微服务的重要基石,如果模块化设计较差的系统,不仅会增加微服务拆分的成本,更为重要的是,会增加形成分布式单体的概率和风险。
本文仅供学习!所有权归属原作者。侵删!文章来源: 京东技术 -胖仔 :http://mp.weixin.qq.com/s/IR_YdEOr6XlSojPzte_QvA
文章评论