作者:京东科技康志兴
前言
从着重表里阻隔的六边形架构,逐渐发展衍生出的层层递进、重视范畴模型的洋葱架构,再到和DDD完美契合的整齐架构。架构风格的不断演进,其实便是为了习惯软件需求越来越杂乱的特色。
可以看到,越现代的架构风格越倾向于清晰的职责定位,且让范畴模型成为架构的中心。
依据这些架构风格,在软件架构规划过程中又有十分多的架构分层模型。
传统三层架构
传统服务通常运用三层架构:
•门面层: 作为服务露出的进口,处理全部的外部恳求。部分情况下,门面层乃至不需求独自界说目标而是直接运用服务层的实体界说。
•服务层: 作为中心事务层,包括全部事务逻辑。并对根底层才能进行简略组合提供必定的才能复用。通常服务层会进行实体界说来防止下层目标体直接露出给外部服务,导致底层任何变化都有可能直接传递到外部,十分不稳定。
•根底层: 用来寄存dao和外部rpc服务的封装,二者可以拆分为不同的module,也可合二为一,以不同package进行阻隔。
三层架构特色便是简略,适用于一些无杂乱事务场景的小型运用,或者“数据不可变”作为根底准则的DOP(面向数据编程)服务。
但是当事务场景稍微杂乱一些、调用层级较多时,可复用性、可维护性就都十分差了,很多代码都耦合在一同,牵一发动全身。

DDD架构
DDD架构可以看做是整齐架构的一种实现,分层职责如下:
•适配层: 用来做外部不同端恳求的适配器,阻隔不同端的协议差异,包装不同端不同样式的呼应体。
•运用层: 用例、使命进口、消息队列监听均在这一层,可以了解为事务流程的进口,经过聚合根的构造履行相应的指令操作。
•范畴服务层: 包括中心的范畴服务界说,并界说了gateway来做一层依靠倒置,使根底设施层仅做实现。
•根底设施层包括全部根底才能:数据库、ES、长途调用封装等等。

长处
•中心稳定: 范畴模型在依靠链上是顶层角色,不依靠任何其他模块,所以极其稳定。其他任何事务域、存储、边际才能的变化都不会对范畴模型形成影响。
•灵敏: 适合不同团队一同开发和维护而不会产生抵触。
•可拆分: 当有届上下文跟着演进逐渐膨胀时,很简略拆分红微服务。
•可扩展: 增加新的功能十分简略,然后使得开发人员可以更快的布置和调整。
•可演进: 良好的可测试性带来十分低的重构本钱,不会跟着不断迭代导致项目成为难以修正的“大泥球”。
如此多的长处天然带来清晰的缺陷
•专业性要求较高: 需求对事务、架构准则了解深入的人员进行规划和维护,不恰当的范畴模型将使后续迭代极为痛苦。
•开发本钱高: 杂乱的架构规划,更多的架构分层,天然带来代码行数的指数级增长。尤其是项目前期的开发使命变得反常繁重。
•不再适合简略的事务场景: 实现一个简略的CRUD显得过于杂乱。
•改动决议计划困难: 尝试运用整齐架构需求和团队的管理层和其他成员达到一致,这往往需求十分强大的说服力。假如在架构演进过程中想切换回其他架构形式也十分困难,简直是整个项目等级的重构作业。
简略的微服务分层架构
依据六边形架构标准的接口适配准则和防腐理念,一起借鉴了CQRS形式的长处,咱们界说了一个简略的微服务分层架构。

分层界说如下:
•门面层: 作为程序的进口,经过包阻隔来寄存JSF服务、Rest服务、守时使命和MQ消费,其中对外提供服务的接口界说寄存在独自的api包中。该层的恳求界说命名以Request结束,呼应体命名以Response结束。
•范畴服务层: 每一个范畴服务寄存在独自的module中,并经过独自的api包对外露出才能。该层的指令恳求界说命名以Command结束,查询恳求界说命名以Query结束,呼应体命名以Dto结束。
•根底设施层: 寄存数据库、ES、长途调用服务的封装。该层的持久化数据界说命名以Po结束。长途指令服务入参命名以RpcCommand结束,长途查询服务入参命名以RpcQuery结束,呼应体命名以RpcDto结束。
最佳实践
1.指令服务必须拜访范畴服务层,允许简略查询直接调用根底设施层。
2.参数校验、恳求出入参日志、审计日志记录、TraceID预埋、反常处理等非中心事务才能均由公共组件完结,削减项目内部的边际才能代码。
3.因为在门面层进行一致的反常处理,非必要时无需在项目中进行大面积的try-catch,让代码更清爽。
4.实际开发过程中,门面层、范畴服务层和根底设施层均有各自的实体界说,跨层调用的目标体转化运用MapStruct组件来削减手写映射代码的作业量。
5.数据层运用Fluent-Mybatis,最大长处是削减后期迭代中,数据目标增减字段时修正Mapper的本钱。
长处
- 开发功率
简略的事务开发过程中,相比较书写中心事务逻辑,更多的作业量简直都是来自处理跨层调用时目标转化和Mapper界说,经过MapStruct和Fluent-Mybatis等组件的运用(或许再加上GitHub Copilot),编写一个实体的增删改查接口基本在5分钟内搞定,省下来的时间可以多走读两遍代码或者多写几个分支的测试用例,也算是降本增效了。
- 服务阻隔
经过module阻隔不同的范畴服务,下降不同范畴服务之间的耦合程度。
- 外部服务防腐
长途调用一致封装在根底设施层中,下降外部变化对系统内部的影响。
缺陷
1.根底设施层的实体作为顶层依靠
因为对根底设施层的依靠没有经过api包进行阻隔,所以根底设施层的目标会直接露出在范畴服务层和门面层。对此可以经过运用ArchUnit组件进行架构防腐。
假如需求界说完善的范畴实体充血模型,主张参阅DDD架构界说gateway层来进行根底设施层的依靠倒置。
最终
软件工程的方方面面都遵从一个最基本的道理:没有银弹,架构分层模型更是如此,每一种都有各自优缺陷,所以请依据不同的事务场景,并遵从简略、可演进这两个重要的架构准则选择适宜的架构分层模型即可。
架构不只是作业,更是一门艺术。
本文正在参与「金石计划」