0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

分层单体架构系统的风格及其本质

OSC开源社区 来源:系统工程实验室 2023-01-16 15:31 次阅读

分层单体架构风格是分层思想在单体架构中的应用,其关注于技术视角的职责分层。

同时,基于不同层变化速率的不同,在一定程度上控制变化在系统内的传播,有助于提升系统的稳定性。

但这种技术视角而非业务视角的关注点隔离,导致了问题域与工程实现之间的Gap,这种割裂会导致系统认知复杂度的提升。

1 经典单体分层架构

1.1 四层单体架构风格

经典的四层单体分层架构如下图所示,应用在逻辑上划分为展现层、业务层、持久层及数据存储层,每层的职责如下:

展现层:负责给最终用户展现信息,并接受用户的输入触发系统的业务逻辑。用户可以是使用系统的人,也可以是其他软件系统。

业务层:关注系统业务逻辑的实现

持久层:负责数据的存取

数据存储层:底层的数据存储设施

6a6a67a0-82a7-11ed-8abf-dac502259ad0.png

这种分层单体架构可能是大多数开发人员最早接触、最为熟悉的应用架构风格,其特点是:

层间的依赖关系由上到下逐层向下直接依赖,每层都是关闭状态,请求的数据流向从上到下,必须严格通过每个分层进行流转,而不能进行穿透调用。

关注点隔离:通过分层将系统的关注点进行垂直分配,每层只关注自身层边界内的职责,层间职责相互独立不存在交叉。比如业务层负责处理系统的核心业务逻辑,而持久层则关注于对数据的存取。

除了关注点隔离这一维度,分层也在 “变化” 的维度进行隔离。每层的变化速率不同,由下级上逐层增加,展现层的变化速率最快,数据存储层变化速率最低。

通过严格层依赖关系约束,尽量降低低层变化对上层的影响。这个特点的上下文是分层之间依赖于抽象,而非依赖于具体。

当实现发生变化而接口契约不变时,变更范围框定在当前层。但,如果是接口契约的变更,则可能会直接影响到上游的依赖层。

这种分层架构风格具有明显的优势:

分层模型比较简单,理解和实现成本低

开放人员接受度和熟悉程度高,认知和学习成本低

1.2 五层单体架构风格

四层架构面临的问题是:

层间数据效率问题: 由于层间调用关系的依赖约束,层间的数据流转需要付出额外成本

业务层服务能力的复用性:业务层中处于对等地位的组件或模块之间存在共享服务的诉求

从复用性的角度考虑,如下所示的五层架构中,通过引入中间层解决复用问题。将共享服务从业务层沉淀到通用服务层,以提高复用性。其特点是:

引入通用服务层提供通用服务,提高复用性

通用服务层是开放层,允许调用链路穿透,业务层可以按需直接访问更下层的持久层

6a81cb20-82a7-11ed-8abf-dac502259ad0.png

相比于四层架构,五层分层架构的主要优势是:通过中间层的引入一定程度解决系统的复用性问题。但从反向角度看,正是由于中间层的引入导致了如下问题:

引入中间层降低了数据传输效率,提高了开发实现成本

有造成系统混乱度提升的风险:由于通用服务层的开放性导致业务层可以穿透调用。

但这种是否需要进行穿透的场景无法形成统一的判定原则,往往依赖于实现人员的个人经验进行权衡,同一个业务场景由不同的开发人员实现可能会有不同的判定结果(在四层架构中如果放开层间调用约束也会存在该问题)。随着业务需求迭代,系统的依赖关系一定会日趋增加,最终形成复杂的调用关系,也导致系统复杂性上升,增加团队成员的认知成本。

6aa45384-82a7-11ed-8abf-dac502259ad0.png

2 单体分层架构的共性问题探讨

当然,正是由于其极高的接受度,也造成了大家对分层的认知误区,认为分层是必然的“默认选项” ,从而忽略了分层的本质。分层到底是为了解决什么问题?

分层本质上是处理复杂性的一种方式:将复杂性在不同级别进行抽象,通过分层进行职责隔离,以此降低认知成本。同时,通过分层形成的“屏障”,控制变化在系统间的传播,提升系统稳定性。

不论是四层架构还是五层架构都是分层思想在单体应用架构风格下的实践,这种分层模式存在的固有问题主要体现在以下几个方面:

分层对系统复杂度和效率的影响

变化真的能完全隔离吗?

问题域与解决方案的隔离

2.1 分层对系统复杂度和效率的影响

如上文所述,分层架构中各层的变化速度不同。越往上变化越快,稳定性越低,越往下变化越慢,稳定性越高。比如,展现层的用户展示逻辑可能频繁变化,对应于不同的场景诉求展示数据及形式都可能不同。

6ac130d0-82a7-11ed-8abf-dac502259ad0.png

如果划分层次越多,层间依赖关系越严格,则系统的调用链路和依赖关系会更加清晰。但,请求及响应的链路越长,层间数据转换有额外成本。即使引入各种数据转换工具,比如MapStruct,实现起来依然会感觉非常繁琐和重复。

如果划分层次越多,层间依赖关系宽松,允许跨层调用(如下所示的从展现层调用持久层只是一个示意),则能在一定程度降低数据频繁转换的成本。但:

其一:如何判定是否要跨层调用很难形成统一的严格判定标准,只能进行粗粒度划分。因此,在实现过程中会有不同的判定结果,系统的调用关系会随着代码规模增长而日趋复杂。当然,团队可以加强代码评审的粒度,每次评审基于是否穿透调用进行讨论、判断并达成一致。但实际经验是,由于人为因素,靠严格的代码评审并不能保证决策的一致性。

其二:如果允许跨层调用,则意味着 “模型” 的穿透,低层的模型会直接暴露在更上层,这与我们追求的组件内聚性和模型的封装性存在冲突

注:层间的依赖约束是一种架构决策,可以考虑通过自动化单元测试机制进行保证

2.2 变化的隔离

我们对分层有一个普遍的、“先入为主” 的认知,分层能够隔离变化。首先会想到的例子,比如,如果底层的数据库发生了变更,又或者ORM框架发生了变更,那么,我们只需要修改DAO层的实现,而不需要更改上层的业务层代码。

你真的会替换数据库吗?你真的会替换ORM框架吗?有可能,但概率非常低,大部分系统并不会发生这种场景。

发生替换就真的能隔离吗?如果你的层间不是依赖于抽象,而是依赖于具体,那么隔离也无从谈起。

即使层间依赖于抽象,变化就真的隔离了吗?实现发生变化的直接结果就是依赖方需要引用新的实现,这种变化也同样会影响到上层。只不过是基于现在的普遍技术栈,这种变化交由IOC容器了

但,这个变化隔离的全部吗?

如果是展现层需要增加一个新的字段,而当前数据库模型中没有?

如果是数据库中需要增加一个新的字段,而展现层和业务逻辑层不关心?

如果是......

所以,引起系统变化的原因很多,场景各异,业务诉求亦不相同,分层对变化隔离程度也不相同:

分层可以控制变化在系统内的传播,由于变化场景的多样化,分层不能完全的隔离变化。

6ad7121a-82a7-11ed-8abf-dac502259ad0.png

2.3 问题域与解决方案的割裂

重新思考下上文提到的分层单体架构的特点之一:关注点隔离,展现层、业务层、数据访问层、存储层等各层聚焦于自身的职责。这种关注点的本质是什么?

技术视角的隔离!!!

每层都是从技术视角将技术关注点进行隔离,而非业务领域视角。技术视角是研发友好的,作为开发人员,天然的可以理解和接受这种技术维度的统一语言:DAO层只负责处理数据相关逻辑,Controller层之服务处理Restful API相关,RPC层只处理与外部系统的跨进程调用等等。

而对于非常核心的业务概念,比如以订单为例,在单体分层架构下需要回答这样一个问题:“订单组件” 在哪里?

在经典的分层单体架构风格中,典型的实现如下图所示:

OrderConroller:Spring技术栈下的系统访问的Rest接口

OrderService/OrderServiceImpl:订单的核心业务逻辑实现服务,实现诸如下单、取消订单等逻辑

OrderDAO/OrdeDAOImpl:订单数据的存取

6af266fa-82a7-11ed-8abf-dac502259ad0.png

订单组件并不是以一个单一的、内聚的事物存在,其组成元素OrderService以及其依赖的OrderDAO分散于不同的层,因此,这种模式下订单组件只是逻辑性、概念性的存在。作为业务域的核心抽象,订单组件没有真实的、直观的、内聚的反映在代码实现中。我们在工程代码库中寻找“订单组件”:

首先,在工程顶层最先看到的是技术视角的Module(Maven Module):web、service 、dao

然后,需要在各层导航才能一窥其全貌

在IDE的支持下,这种导航并不会很复杂。但问题的根本在于:认知成本的增加。

我们去了解系统,天然的是从业务域而非技术域出发,单体分层恰恰是从技术域而非业务域出发,这种不同导致业务域与实现间的割裂,增加了对系统的认知成本。

实现要反应抽象,组件化思维本质上一种模块化思维,通过内聚性和封装性,将问题空间进行拆分成子空间,分而治之。对外通过接口提供组件能力,屏蔽内部的复杂性。接口契约的大小粒度需要权衡,粒度越小,能力提供越约聚焦,理解和接入成本越低,但通用性越差。接口契约粒度越大,则通用性越强,但理解和接入复杂性越高。

6b0bdf90-82a7-11ed-8abf-dac502259ad0.png

将组件化思维应用于单体分层架构,引申出模块化单体架构风格。应用架构按照问题域进行模块化组织,而非基于技术关注点进行拆分。组件内部遵循内聚性原则,其内包含了实现组件能力所需要的各个元素及交互关系。组件之间通过统一的、合适粒度的接口契约进行交互,不直接依赖于组件的内部能力或模型。

同时,组织良好的模块化单体应用架构也是进行微服务拆分的重要保证。如果你无法在单体架构中进行优雅的模块化组织,又何谈合理的微服务拆分呢?

6b252838-82a7-11ed-8abf-dac502259ad0.png

3 结语

单体分层架构风格是分层思想在单体架构中的应用,其关注于技术视角的职责分层。同时,基于不同层变化速率的不同,在一定程度上控制变化在系统内的传播,有助于提升系统的稳定性。但这种技术视角而非业务视角的关注点隔离,导致了问题域与工程实现之间的Gap,这种割裂会导致系统认知复杂度的提升。

将组件化思维应用于单体分层架构,模块化单体技术视角的分层拉回至业务域视角的模块化,一定程度上降低了业务于工程实现间的隔离。良好的模块化是单体走向微服务的重要基石,如果模块化设计较差的系统,不仅会增加微服务拆分的成本,更为重要的是,会增加拆分后形成分布式单体的概率和风险。






审核编辑:刘清

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 数据存储
    +关注

    关注

    5

    文章

    898

    浏览量

    50589
  • RPC
    RPC
    +关注

    关注

    0

    文章

    102

    浏览量

    11424
  • IOC
    IOC
    +关注

    关注

    0

    文章

    28

    浏览量

    10050

原文标题:分层单体应用架构的本质

文章出处:【微信号:OSC开源社区,微信公众号:OSC开源社区】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    随身wifi的本质是什么?

    本帖最后由 法藏 于 2015-3-6 16:45 编辑 随身wifi的本质是什么?360随身wifi从一代到三代,售价如此低廉,其本质到底是何?
    发表于 03-06 16:19

    为什么要有BMS系统?电池单体的“参谋”与“将军”!

    时又是从一个充电口来为车子充电,如何保证每一块电池都充满电,而又不会因为过度充电对电池造成损害就是BMS系统要解决的问题之一。那么bms系统究竟是如何管理这么多电池单体的呢?  通常情况下,BMS
    发表于 01-22 16:08

    AUTOSAR分层架构

    AUTOSAR分层架构
    发表于 09-26 11:12

    Android操作系统分层架构是怎么样的

    我晓得Android 操作系统是一个开源的,还是有很多不懂,在网上查了下,看到Android一词的本义指“机器人”,最初的Android主要支持手机,后来经过开发改良,逐渐扩展到平板电脑及其他一些
    发表于 03-05 06:45

    认识其本质模拟SPI硬件SPI图片写入函数封装

    认识其本质模拟SPI硬件SPI图片写入函数封装
    发表于 08-03 06:17

    电池管理系统的硬件架构

    ),AUTOSAR的分层模型架构使得主机厂、供应商、科研机构可以联合开发、高效配合,构造出强大的软件系统。图2成熟的BMS软件开发通常是基于AUTOSAR架构开发。AUTOSAR
    发表于 09-15 08:20

    嵌入式分层架构的相关资料分享

    最近重新进入嵌入式领域,有必要对嵌入式分层架构有一个清晰的理解。经过多方查阅以及个人的理解,本人对嵌入式分层架构概括总结如下:比较细的层次由下到上可分为:(硬件层)硬件底层->硬件驱动
    发表于 10-28 08:42

    基于mcu的一种分层软件架构的相关资料分享

    基于mcu的一种分层软件架构(一)1、写在前面先来个图:经过了一段时间的琢磨与思考。借鉴操作系统分层原理,也搞出来了一种mcu的层状软件结构。好了,不说虚的啦。所有的一些方法和思想,
    发表于 11-03 06:46

    单片机复位的本质是什么呢

    英文词汇,充分说明了其本质:重新设定。通俗点儿说,就是 ” 从头开始 “ 之意。我们对磁盘进行的格式化操作(format),其本质也是一种 “Reset” 操作。只不过这个 " Reset
    发表于 11-03 09:16

    基于多尺度笔刷的分层图像优化风格化绘制算法

    基于图像的油画风格化绘制是计算机图形学领域非真实感绘制研究的热点之一。为了进一步提高图像油画风格化的质量,提出了一种基于多尺度笔刷的分层图像油画风格化绘制算法。该算法模拟艺术家的油画绘
    发表于 06-07 11:23 5次下载

    AUTOSAR分层架构介绍及SmartSAR studio使用总结

    AUTOSAR分层架构
    发表于 03-28 16:44 9次下载

    单体架构如何向分布式架构转型

    任何一个架构风格,都可以实现功能性需求,但是一个好的架构风格能在功能性需求之上,提升非功能性需求。那么你可能会问,什么是非功能性需求?举例:扩展性、稳定性等等。
    的头像 发表于 10-20 10:28 674次阅读

    分层架构到微服务架构介绍(一)

    们看到一个架构模式的名字时,也要马上想到对应的架构及其基本特点。比如,当谈到**分层架构**时,我们就应该想起它的
    的头像 发表于 05-10 16:55 811次阅读
    从<b class='flag-5'>分层</b><b class='flag-5'>架构</b>到微服务<b class='flag-5'>架构</b>介绍(一)

    分层架构到微服务架构介绍(五)

    本文要介绍的是 服务化架构 (Service-Based Architecture, SBA )。 SBA 可以看成是单体架构和微服务架构之间的一个折中方案,它也是按照业务领域进
    的头像 发表于 05-10 17:02 595次阅读
    从<b class='flag-5'>分层</b><b class='flag-5'>架构</b>到微服务<b class='flag-5'>架构</b>介绍(五)

    电路设计中有几种地?各类GND的含义及其本质

    电路设计中有几种地?各类GND的含义及其本质  在电路设计中,地是非常重要的一个概念,它是整个电路中的参考地点,同时也是信号回流的路径。在电路中,不同的地具有不同的含义和本质,下面我们来详细了解一下
    的头像 发表于 10-26 11:38 588次阅读