什么是分层架构
在软件工程中,分层架构是一种常见的设计方式,它将整个系统划分为多个层次,每个层次都有独立的职责,它们协同工作以提供完整的功能。当我们初次进入编程领域时,通常会学习并强调采用”MVC”(Model-View-Controller)架构。MVC将整个系统分为三个关键层次:模型(Model)、视图(View)和控制器(Controller)。这一架构的核心思想是将用户界面和业务逻辑分离,并通过控制器来协调它们之间的交互。MVC成功实现了视图和逻辑的解耦,因此被广泛认可为一种标准的软件分层架构。
另一种常见的分层方式是将整体架构划分为三个关键层次:
-
表现层、逻辑层和数据访问层。表现层负责展示数据结果和接收用户指令,是最靠近用户的一层;
-
逻辑层包含了复杂业务的具体实现;
-
数据访问层主要处理和数据库之间的数据交互。
事实上,我们在实际项目中已经习惯按照这种三层架构进行系统分层设计。例如,当我们构建项目时,通常会创建三个主要目录:Web(用于表现层)、Service(用于逻辑层)和Dao(用于数据访问层),这些目录分别对应了这三个关键层次的功能。
此外,我们可以发现许多其他分层的例子,这些例子有助于组织和管理复杂系统。举例来说,我们学习的OSI网络模型将整个网络分为七个层次,自下而上分别是物理层、数据链路层、网络层、传输层、会话层、表示层和应用层。在实际工作中,TCP/IP协议简化了网络结构,将网络分为四个层次:链路层、网络层、传输层和应用层。每个层次都有明确定义的职责,它们相互合作,确保网络正常运行。例如,网络层负责端到端的寻址和建立连接,传输层负责端到端的数据传输,不同层次之间进行数据交互。这种分层方式有助于分离关注点,使不同层次可以专注于不同的任务。
分层有什么好处
分层的设计在简化系统架构方面具有显著的优势,它使不同的人可以专注于特定层次的任务。想象一下,如果没有分层,你需要设计一个网络应用程序,这将是一项非常困难的任务。因为你必须具备广泛的网络知识,了解各种网络设备的接口细节,以便能够发送数据包。你还需要处理数据传输的各种复杂细节,如网络拥塞和数据重传。此外,你还需要考虑网络安全性,以防止数据被窃取或篡改。然而,有了分层设计,你只需专注于应用层的程序设计,而其他任务可以由下层来处理。
此外,分层设计也有助于高度的代码复用。当你在设计系统A时,如果发现某一层具有通用性,你可以将其抽象为一个独立的组件,然后在设计系统B时重复使用。这可以减少开发周期,提高开发效率。
最后,分层架构还使横向扩展更加容易。如果系统没有分层,当流量增加时,你需要对整个系统进行扩展。然而,如果按照三层架构将系统分层,你可以有针对性地扩展特定的层次。例如,如果业务逻辑层包含复杂的计算,导致CPU性能成为瓶颈,你可以将逻辑层独立部署,并只对逻辑层进行扩展。这相比对整个系统进行扩展要更加高效和经济。
如何来做系统分层
在进行分层设计时,有一些关键因素需要考虑。其中,最重要的因素之一是要清晰地定义每个层次的边界。你可能会问:“如果我们按照三层架构进行分层设计,每个层次的边界不是很明显吗?”确实,当业务逻辑相对简单时,层次之间的边界通常很清晰,你知道在开发新功能时应该将代码放在哪个层次。然而,随着业务逻辑变得越来越复杂,这些边界可能会变得模糊不清。允许我用一个示例来说明。
在任何系统中,都会有用户系统,其中最基本的接口之一是用于返回用户信息的接口。这个接口通常会调用逻辑层的GetUser
方法,而GetUser
方法则会与用户数据库交互以获取数据。这就是左侧图表所示的情况。现在,产品提出了一个需求:在应用程序中展示用户信息时,如果用户不存在,系统应自动创建一个新用户。同时,还需要创建一个HTML5页面,但该页面应保留之前的逻辑,即不需要自动创建用户。在这种情况下,逻辑层的边界变得模糊,表现层开始承担部分业务逻辑,将获取用户和创建用户接口协调在一起。
这个例子突出了在复杂业务环境中,层次之间的边界可能会变得模糊,需要更仔细的考虑和规划。因此,在分层设计时,确保清晰定义每个层次的职责和边界非常关键。
那我们要如何做呢?我们可以将原先的三层架构细化成下面的样子:
让我来解释一下这个分层架构中每个层次的作用:
-
终端显示层:这一层负责处理各种端的模板渲染和显示任务。具体来说,它包括Velocity渲染、JS渲染、JSP渲染、移动端展示等。终端显示层的任务是将数据呈现给用户。
-
开放接口层:在这一层,Service层的方法被封装成开放接口,同时进行网关安全控制和流量控制等。这一层充当着对外提供服务的门面,同时确保安全和流量控制。
-
Web层:Web层主要负责访问控制的转发,执行各种基本参数校验,以及处理一些不需要复用的简单业务。它处理与用户请求直接相关的任务。
-
Service层:这是业务逻辑层,包括了系统的核心业务逻辑。Service层负责执行具体的业务操作。
-
Manager层:Manager层具有两个主要作用。首先,它可以将原本在Service层的通用能力下沉到这一层,例如与缓存和存储的交互策略以及中间件接入。其次,Manager层还可以封装对第三方接口的调用,比如支付服务、审核服务等。
-
DAO层:数据访问层,用于与底层数据库(如MySQL、Oracle、HBase等)进行数据交互。这一层负责数据的持久化和检索。
-
外部接口或第三方平台:这包括与其他部门的RPC开放接口、基础平台和其他公司的HTTP接口等。在系统中与外部系统和服务进行通信的层次。
在这个分层架构中主要增加了 Manager 层,它与 Service 层的关系是:Manager 层提供原子的服务接口,Service 层负责依据业务逻辑来编排原子接口。
以上面的例子来说,Manager 层提供创建用户和获取用户信息的接口,而 Service 层负责将这两个接口组装起来。这样就把原先散布在表现层的业务逻辑都统一到了 Service 层,每一层的边界就非常清晰了。
除此之外,分层架构需要考虑层次之间一定是相邻层互相依赖,数据的流转也只能在相邻的两层之间流转。
我们还是以三层架构为例,数据从表示层进入之后一定要流转到逻辑层,做业务逻辑处理,然后流转到数据访问层来和数据库交互。那么你可能会问:“如果业务逻辑很简单的话可不可以从表示层直接到数据访问层,甚至直接读数据库呢?”
其实从功能上是可以的,但是从长远的架构设计考虑,这样会造成层级调用的混乱,比方说如果表示层或者业务层可以直接操作数据库,那么一旦数据库地址发生变更,你就需要在多个层次做更改,这样就失去了分层的意义,并且对于后面的维护或者重构都会是灾难性的。
分层架构的不足
分层架构虽然具有众多优势,但也存在一些缺陷。其中最显著的缺陷之一是增加了代码的复杂性。这一点显而易见,因为本来可以直接在接收到请求后查询数据库并获取结果,但现在必须在中间插入多个层次,其中许多层次可能只是简单地传递数据。有时,即使是一个小小的需求变化,也可能需要更改所有层次上的代码。这看起来会增加开发成本,并且在调试方面也会增加复杂性。在原本的情况下,如果直接访问数据库,只需调试一个方法,但在分层架构中,可能需要调试多个层次的多个方法。
另一个潜在的缺陷是,如果每个层次都独立部署,层次之间通过网络进行交互,那么多层架构在性能方面可能会有一些损耗。这也是为什么服务化架构的性能可能略逊于单体架构的原因,因为它涉及到所谓的“多一跳”问题。
然而,尽管分层架构存在这些缺陷,我们仍然应该选择它。分层架构的优势远远超过了这些缺陷,它有助于组织和管理复杂系统,提高了系统的可维护性和可扩展性。此外,好的设计和适当的抽象可以在一定程度上减轻代码复杂性,并且在性能方面的损耗可以通过优化和合适的架构选择来弥补。因此,分层架构仍然是一种非常有价值的架构设计模式。
你要知道,任何的方案架构都是有优势有缺陷的,天地尚且不全何况我们的架构呢?分层架构固然会增加系统复杂度,也可能会有性能的损耗,但是相比于它能带给我们的好处来说,这些都是可以接受的,或者可以通过其它的方案解决的。我们在做决策的时候切不可以偏概全,因噎废食。
原文始发于微信公众号(二进制跳动):国庆专栏-架构分层:我们为什么一定要这么做?
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/166979.html