写点什么

论层次架构风格

用户头像
lazytortoise
关注
发布于: 2 小时前
论层次架构风格

摘要

本文以 2020 年 3 月,我主持研发了公司《积分开放平台项目》为实例,探讨了企业应用系统的分层架构风格,认为分层架构符合当前项目架构设计,首先简单阐述每个层次的主要功能,然后结合实际情况说明每个层次设计时,需要注意的问题及相应的解决方案。

在项目中,我担任了系统架构设计师,参与了公司积分开放平台架构设计工作,实践证明,在项目开发中,使用了分层架构,加速了项目进度,降低了项目风险,节省了项目开发成本,使系统具有良好的扩展性、关注点分离、可移植性、开放性。系统上线以来运行稳定,得到相关领导的高度认可。

正文

本司有着 N 多年银行保险礼品服务、营销策划服务背景,大多数业务都是线下,随着银行保险业务不断线上化,公司的业务正在从传统转向移动互联网,相关积分线上对接业务也不断产生,为了让对接标准化和效率化,积分开放平台项目应运而生,主要职责对接客户方已有积分接口,以及开放其他能力给第三方完成积分兑换等营销活动。

分层架构风格是目前最常见的架构风格,也是属于调用/返回风格。分层的好处,好比:分工,各司其职,每个人都可以从事最擅长的劳动,使得劳动力大幅超提升,优点:分离开发人员关注点,无损替换,降低了系统之间的依赖,复用,缺点:可能存在级联修改问题,这个功能所有层都需要修改,性能问题,但只要控制分层层级不要太多,性能问题基本可以忽略不计。公司给团队有一个指标:架构需要支持单体到微服务无缝衔接。

本系统后端使用 Golang 语言开发,整个系统采用前后端分离,后端部分基于自研的 Go 框架进行开发,采用分层架构风格,为了满足当前单体开发需求和微服务改造的便利性,以及代码领域代码复用性考虑,经过研发团队确定采用大四层小六层架构,按逻辑上层次划分为四层,分别有用户接口、应用层、领域层、基础设施层,按代码物理分层分为小六层,分别有用户接口层、应用接口层、应用实现层、领域层、数据操作层、基础设施层。

代码架构如下:用户接口层(顶层)-> 应用服务接口层 -> core(应用服务实现层->领域层->数据库操作层)->基础设施层,其中 core 是指应用服务实现层呢过、领域层、数据操作层都在同一个文件下,接下来按照物理分层的方式来介绍系统分层架构。

用户接口层的职责主要包含向上沟通的职责,为不同协议提供用户接口(交互协议入口),比如 http 协议或者是 grpc,当前系统主要优先实现了两种协议:http、gRPC 协议,http 是了客户方系统调用方便,gRPC 是方便公司内部 java 项目有需要调用。每一个文件都是单独的入口,都配置自有的路由信息,方便代码拆分到独立的仓库,进行微服务改造。

应用服务接口层主要职责负责对外暴露接口以及定义入参 DTO、出参 DTO 信息对象。

应用服务实现层的职责是表达用户故事,应用接口实现层主要负责实现应用服务接口的接口,主要表达用户故事,数据校验、安全、日志也都放在这一层实现,是比较薄一层。高层模块不能依赖底层具体实现,而是应该依赖抽象,这样设计也是符合依赖倒置原则。该层的代码放置在核心层文件夹下,通过小写包名来限制包外调用,通过框架来限制不规范的使用。

领域层是核心,主要负责凝练业务规则集合,几乎所有是业务逻辑会在该层实现,是核心的核心,是比较重的一层,主要包含实体(具有唯一标识)、值对象(无需唯一标识)、领域对象(与业务逻辑相关,具有属性和行为的对象)、聚合/聚合根(聚合是指一组具有内聚关系的相关对象的集合)、工厂(创建复杂对象,隐藏创建细节)以及事务。该层的包名均为为小写,仅在核心层中进行使用,目的是仅能上层服务接口层进行业务接口暴露,在项目的执行中还遇到了一些为问题,比如传统领域驱动四层架构中对事务描述是适合放在应用层,因为应用是面向用例设计,为什么事务会在这一层?主要是为了方面聚合内数据的一致性,按照公司的存量和规模是有可能,架构演化是极有可能演化到微服务,而微服务的产生很容易联想到会分布式事务(2PC/3PC/Saga/TCC/MQ 等),如果在应用层描述用例中使用了事务,从写法很容易把多个聚合下的事务形成一个大事务,如果是放在领域层,只会有当前业务域内的事务,相当于本机事务,事务的一致性仅在业务域范围内部更加可用,无需引入分布式事务。部分有关联业务域可用遵循 BASE 理论的最终一致性。

数据操作层的职责是最小单元的数据库操作代码是在这一层。该层会对定义数据持久化对象,会对应用服务层定义 DTO 到持久化对象相互转换场景。领域层会实例化一个数据库操作对象传递到该层,方便多个单元的数据操作成为一个事务。

基础设施层是最底层,职责主要包含为其他层提供向下沟通的能力,保存运行状态,包含一些基础公共资源和基础算法,基础组件:gorm mysql、elasticseearch、viper(配置文件)、validator 验证器、Nacos、redis、prometheus、log、hook、gin 等基础组件,基础算法包含:负载均衡算法等基础算法。基础资源如此之多,而且有些基础资源有相互依赖的部分,比如 redis、mysql 就需要先读取配置信息之后才能进行初始化,有些资源是在启动的时候,是同步阻塞执行,有些资源是启动异步执行,面对这些情况,在项目中,我们对基础资源的生命周期进行了抽象,包含初始化、安装、启动、停止、启动时是否异步、在需要该基础资源的时候将其注册到启动管理器中,然后循环遍历启动管理器,调用启动器的初始化、安装、启动方法,只要对应资源实现了相关对应抽象,这样基础组件就像插件一样,在需要使用地方才进行注册启动。在停止方面,我们在 Hook 中实现 kill 消息监听,方便服务优雅关停。另外,为了后续自研或者替换产品,我们在基础组件之上简简单单的封装了一层,方便以后替换。

总结,项目在公司运营一年多,目前最近还进行了微服务的实施,总体效果不错,得到领导和同事的一致认可,但是存在保留出一些:Docker 容器技术不熟悉,产生项目初始化延误,导致对项目的进度造成影响,最后通过应急处理和协调,才影响到项目的总体进度。我们已经把这些经验和教训,总结到工作总结里面,向其他技术人员分享,为今后系统架构设计提供帮助,相信通过不断持续学习改进,加强自己系统分析与设计能力,努力工作提升工作水平,为社会和公司多贡献一点自己的价值。

发布于: 2 小时前阅读数: 7
用户头像

lazytortoise

关注

还未添加个人签名 2019.04.15 加入

还未添加个人简介

评论

发布
暂无评论
论层次架构风格