一文搞清微服务的分层设计
掘金账号:橘松Java
微信公众号:橘松Java技术窝
文章首发掘金平台,后续同步更新公众号,关注后回复 "加群" 可加入互联网技术交流&内推群,和一群大厂大佬讨论面试问题。回复 "666" 可获取一线互联网具备所有资料包(包括开发软件、开发规范、经典电子pdf、以及一些精品学习课程)。
「本文已参与好文召集令活动,点击查看:后端、大前端双赛道投稿,2万元奖池等你挑战!」
前言
在设计复杂的系统时候,分层是最常用的一种手段,最简单的分层莫过于大家熟悉的mvc三层理念。
而对于大多数互联网公司来说,一般将其分成五层:基础设施层
、领域服务层
、应用服务层
、网关层
、用户表示层
别着急 ,慢慢絮叨,传统的三层模式是指控制层、服务层、数据存储层;然而随着微服务架构一直主流在互联网中,之前的分层模式已经不能承载我们既有的业务了,下面先谈谈对这五层的具体理解。
基础设施层
代表资源、存储,底层的能力支撑,它对业务无感知。
领域服务层
和应用服务层
在微服务设计中都是可以进行拆分的,领域服务层
可以按照DDD领域设计
进行领域划分
,被设计成一个个领域模块的微服务
,每个微服务之间高度内聚,它们只关注本身的业务,相互之间通过接口调用来进行通信。至于领域服务层和应用服务层它们之间的不同就是领域服务层是桥接在应用服务层和数据层之间的,应用服务层更加关注领域模型多一些,而领域服务层更加关注数据模型多一些.
网关层
和用户表示层
比较好理解,是承接前端适配以及渲染、聚合数据的分层,它们之间基本无核心业务的逻辑,主要是担任接口准入校验以及参数模型转换的一些工作。
这种分层设计方案可以大大的简化复杂的大系统,并且在后期维护迭代中优势会日渐凸显,但是如何划分好和拆分好?,什么代码放到哪一层?,每一层和每一层我应该注意些什么? 将是我们开发者需要研究思考的问题。
别急! 下文将会详细探讨这五层背后的本质以及巧妙之处。(本人工作年限不是很长,如果有理解不到位的地方请各位大佬海涵,留言指出)
分层设计
分层设计和DDD没有必然的联系,最开始做项目的时候像数据库访问的也是在系统的业务包下,后面接触了分离设计才知道这其实不好扩展,也就是现在的四层分层设计更合理一些。当然这是建立在比较复杂系统的逻辑分层,这里强调的不是每一层都是在系统的内的不同模块,它们可以是一个个独立的微服务,每个域的模块即是一个或多个微服务。
在Web应用系统中会引入网关层来衔接用户表示层和应用服务层,对应用服务层的对外包装 但是网关层不是必须要的,也可以直接暴露应用服务层来对接用户表示层,只需要通过一些验证、授权、统一接入层即可。
应用服务层是负责表达你的领域概念模型来解决问题,关于领域模型不清楚的可以看
一文讲清领域模型和数据模型。一般是需要前期梳理出此服务的建立的目标是用来解决什么问题,这个问提涉及到哪些业务领域模型,这一层要做到尽量简单,不要包含任何你的业务规则,只是为了调度下一层中的领域对象来完成任务。
应用服务层是面向用户的功能定义,将用户的指令转化为领域层所需的输入模型即可,而业务的规则,业务的细节、实现等复杂的过程都应该在领域层来实现。
领域服务层是负责表达业务规则、业务状态,这一层应该要做到能清晰的感知业务的数据流转,关键核心流程所向,尽管具体的操作指令是通过发送到仓储层(基础设施层)来完成,领域层是业务软件的核心。
基础设施层是负责为其上几层提供通用的技术能力,对上层业务无强感知,为领域服务层提供持久化机制,为应用层传达消息。在软件系统中,一般包括数据持久化服务以及各种中间件服务(MySQL
、Redis
、Memcached
、ELK
等)。
每层之间各司其职,不过基本都要满足下面这些原则
- 每一层的设计都需要保持严格内聚,不存在跨层依赖,只能依赖它的下一层。
- 如果说下层需要和上层通信,不能通过
Interface
方式通信,只能通过中间件组件(MQ
、CallBackListener
等技术) 来进行。 - 每层之间交互需要保证松散耦合,也就是上层只需要依赖下层的
api
包,在很多RPC框架中均是如此,而在SpringCloud
、Serviceless
架构中不是如此,它们将更加松散,最大化的降低了系统耦合。
如何进行领域划分
其实这个话题没有一个明确的答案,规则。相同的业务可能在不同的场景下也不尽相同。但是朝着这个方向去设计一定能让你的系统更具有弹性。我总结下我个人的一些思考,供大佬们围观
首先,我认为领域设计一定要有清晰的边界,体感就是接到一个需求,你应该能快速知道这个需求我会改动哪几个服务,每个服务改哪些代码。一个领域服务其实对应的是一组功能的集合,这些集合是有一定的共性的,比如都有相同的实体(Entity),值对象(Value Object
。比如商品服务,那么像创建商品、修改商品、商品上下架、查询商品列表,都属于商品域的功能集合。
领域拆分也不是一步到位的,因为你无法预知几年后的业务发展方向,应该根据实际情况、划分出领域的细度,如果一开始就拆的很细方案那么一定会死得很惨,应该是先粗粒度的划分,然后如果需要,在从某个粗粒度划分出多个细粒度,比如商品中心IC(item center)
一开始划分商品服务,随着商品业务越来越复杂,可能需要划分出类目服务、库存服务、价格服务等
领域层服务应该和调用者无关。因为一个好的领域服务只需要关心输入和输出,提供的能力服务一定是通用的,面向领域开发而不是面向功能开发。比如订单域 有一个下单服务接口设计成createOrderForIC
,给 商品中心IC(item center)
调用,如果有其他域需要创建顶单,比如第三方渠道等,那么这个服务接口将不可用,应该设计成createOrder
。
想了解更多的关于领域建模相关知识,请持续关注领域建模实践专栏 。
最后
- 文章均原创,原创不易,感谢掘金平台,觉得有收获,帮忙三连哈,感谢
- 微信搜索公众号:橘松Java技术窝,交个朋友,进互联网技术交流群
- 文章涉及的所有代码、时序图、架构图均共享,可通过公众号加群免费索要
- 文章若有错误,欢迎评论留言指出,也欢迎转载,麻烦标注下出处就好