首页 > IT基础架构 > 服务器/存储 > 单体分层应用架构剖析
1.1 四层单体架构风格
展现层:负责给最终用户展现信息,并接受用户的输入触发系统的业务逻辑。用户可以是使用系统的人,也可以是其他软件系统。
业务层:关注系统业务逻辑的实现
持久层:负责数据的存取

图1.经典的四层单体分层架构示意
层间的依赖关系由上到下逐层向下直接依赖,每层都是关闭状态,请求的数据流向从上到下,必须严格通过每个分层进行流转,而不能进行穿透调用。
分层模型比较简单,理解和实现成本低
1.2 五层单体架构风格
层间数据效率问题: 由于层间调用关系的依赖约束,层间的数据流转需要付出额外成本
引入通用服务层提供通用服务,提高复用性

引入中间层降低了数据传输效率,提高了开发实现成本
有造成系统混乱度提升的风险:由于通用服务层的开放性导致业务层可以穿透调用。但这种是否需要进行穿透的场景无法形成统一的判定原则,往往依赖于实现人员的个人经验进行权衡,同一个业务场景由不同的开发人员实现可能会有不同的判定结果(在四层架构中如果放开层间调用约束也会存在该问题)。随着业务需求迭代,系统的依赖关系一定会日趋增加,最终形成复杂的调用关系,也导致系统复杂性上升,增加团队成员的认知成本。
图3.引入中间层产生问题分层对系统复杂度和效率的影响
变化真的能完全隔离吗?
2.1 分层对系统复杂度和效率的影响
图4.
其一:如何判定是否要跨层调用很难形成统一的严格判定标准,只能进行粗粒度划分。因此,在实现过程中会有不同的判定结果,系统的调用关系会随着代码规模增长而日趋复杂。当然,团队可以加强代码评审的粒度,每次评审基于是否穿透调用进行讨论、判断并达成一致。但实际经验是,由于人为因素,靠严格的代码评审并不能保证决策的一致性。
注:层间的依赖约束是一种架构决策,可以考虑通过自动化单元测试机制进行保证,具体可参考:
《基于ArchUnit守护系统架构》
2.2 变化的隔离
你真的会替换数据库吗?你真的会替换ORM框架吗?有可能,但概率非常低,大部分系统并不会发生这种场景。
发生替换就真的能隔离吗?如果你的层间不是依赖于抽象,而是依赖于具体,那么隔离也无从谈起。
如果是展现层需要增加一个新的字段,而当前数据库模型中没有?
如果是数据库中需要增加一个新的字段,而展现层和业务逻辑层不关心?
分层可以控制变化在系统内的传播,由于变化场景的多样化,分层不能完全的隔离变化。
图5.
2.3 问题域与解决方案的割裂
OrderConroller:Spring技术栈下的系统访问的Rest接口
OrderService/OrderServiceImpl:订单的核心业务逻辑实现服务,实现诸如下单、取消订单等逻辑
图6.在经典的分层单体架构风格中,典型的实现示意
首先,在工程顶层最先看到的是技术视角的Module(Maven Module):web、service 、dao
实现要反应抽象,组件化思维本质上一种模块化思维,通过内聚性和封装性,将问题空间进行拆分成子空间,分而治之。对外通过接口提供组件能力,屏蔽内部的复杂性。接口契约的大小粒度需要权衡,粒度越小,能力提供越约聚焦,理解和接入成本越低,但通用性越差。接口契约粒度越大,则通用性越强,但理解和接入复杂性越高。
图7.
将组件化思维应用于单体分层架构,引申出模块化单体架构风格。应用架构按照问题域进行模块化组织,而非基于技术关注点进行拆分。组件内部遵循内聚性原则,其内包含了实现组件能力所需要的各个元素及交互关系。组件之间通过统一的、合适粒度的接口契约进行交互,不直接依赖于组件的内部能力或模型。同时,组织良好的模块化单体应用架构也是进行微服务拆分的重要保证。如果你无法在单体架构中进行优雅的模块化组织,又何谈合理的微服务拆分呢?
图8.单体分层架构风格是分层思想在单体架构中的应用,其关注于技术视角的职责分层。同时,基于不同层变化速率的不同,在一定程度上控制变化在系统内的传播,有助于提升系统的稳定性。但这种技术视角而非业务视角的关注点隔离,导致了问题域与工程实现之间的Gap,这种割裂会导致系统认知复杂度的提升。将组件化思维应用于单体分层架构,模块化单体技术视角的分层拉回至业务域视角的模块化,一定程度上降低业务与工程实现间的隔离。良好的模块化是单体走向微服务的重要基石,如果模块化设计较差的系统,不仅会增加微服务拆分的成本,更为重要的是,会增加形成分布式单体的概率和风险。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/70027824/viewspace-2981149/ ,如需转载,请注明出处,否则将追究法律责任。