当前位置: 首页 > 科技观察

通过领域驱动建模来划分微服务的真正难点在哪里?

时间:2023-03-19 11:36:04 科技观察

本文转载自微信公众号《说说IT》,作者何明禄。转载本文请联系悦潮IT公众号。今天的文章主要是对上一篇文章没有说清楚的地方做进一步的说明。微服务划分注意,微服务划分涉及两个关键部分。哪些业务功能应该聚合在一起。哪些数据应该聚合在一起,Owner就是微服务。为什么我一直强调这一点。因为在微服务之间传统的单体应用阶段,也是有架构设计和组件划分的。但总的来说,只是如何聚合应用层的业务功能,并不涉及数据库本身的拆分。微服务下的划分,一定是数据和功能的分离。微服务A只能对自己Owner的数据库进行JDBC等直连操作,而对于其他微服务数据库,只能进行应用层暴露的API接口服务。上图中有红叉的地方是不允许的。虽然传统的单体应用架构设计也是分组件的,但一般的数据库是不分组件的。虽然组件也可以独立部署在APPServer上,但底层数据库还是耦合在一起的。因此,单个组件并没有实现数据库到应用层的完全解耦。虽然组件设计开发规范要求组件A需要通过API访问组件B提供的能力,但实际上大多数时候组件A是直接访问后台数据库表的。因为这样开发和实现是最容易的。所有的很多规范约束其实都很难实现,在组件化之后还是处于紧耦合状态。因此,微服务的划分需要同时考虑功能和数据的聚合和拆分。这种划分其实比传统架构设计中的组件划分更难,需要更多的考虑。领域模型划分微服务领域驱动设计概念来自于2004年著名建模专家EricEvans,他还出版了一本经典的领域驱动设计建模书籍。但是DDD本身在很多年前并不是很流行。如果回到10多年前,主流的架构设计思想是RUP+UML,而DDD的建模思想其实更复杂,想要很好地应用起来并不容易。其次,很多IT项目本身并不需要使用如此复杂的建模方法。最近5年,随着微服务架构的流行,DDD领域建模再次受到关注。一个核心的应用点就是如何划分微服务?领域驱动设计中的限界上下文和子域划分给出了一个很好的思路和方法。例如,它通常用于根据事件风暴划分上下文。识别事件和命令事件可以理解为一个事物写入的最终状态,比如订单已创建、支付已完成、产品已发货等都是关键事件。命令可以理解为特定的业务功能或操作,例如创建订单、检索产品和扣除库存。可见,在对事件和命令的识别分析中,可以识别出具体的领域对象。如何基于领域对象进行聚合?简单的说,还是通过识别和整理共同的领域对象来聚合。聚合同一域对象上的所有命令和事件。上下文边界的划分是基于聚合的完成。事实上,如果不同的领域对象属于同一个业务场景,它们仍然可以被划分到一个上下文中。也就是说,不是简单地根据聚合的领域对象来划分上下文边界,而是需要将许多与核心领域对象相关的附属对象也划分到同一个上下文中。比如电商中的订单就是大量的领域对象,可以划分为独立的上下文,但是对应的购物车也是我们识别的对象。购物车本身也属于产品订购场景,是订单的扩展附属对象,所以需要添加购物车,也划分到订单上下文中。整个方法的思路总结如下。即仍然是业务场景驱动分析加上头脑风暴,确定关键业务事件(如果采用Scrum方式,这也可以理解为一个独立的UserStory)。任何业务事件都包含三个元素:业务动作、业务对象和对象状态。注意,在常用的事件风暴方法中,更强调先找到狭义的事件,即对象状态。比如shipped、paid、frozen等状态事件,然后分析状态事件对应的对象和业务操作。当你对某个领域不熟悉时,不必一步步去做,直接通过业务场景和流程梳理出核心细粒度的业务活动点即可。业务活动自然具有对象和状态。把事件分解成这三个元素后,再按业务对象聚类。例如,订单是一个业务对象,它聚合了与订单相关的所有业务事件。聚类完成后,每个簇都是一个独立的限界上下文。Aggregates,BoundedContextsandSubdomains如果你按照上面的步骤把每个聚合划分成一个个的微服务。那么最终的微服务一定是太细粒度了。因为每个核心业务对象都变成了微服务。以传统的供应链系统为例,你会看到采购订单、采购订单、物料、供应商、框架协议、入库单、出库单、库存信息、采购计划等是核心的功能聚合点。那么一个传统的供应链系统需要拆分成几十个微服务?通过事件风暴整理事件,基于对象进行功能聚合,没有错。但是每个聚合本身并不能完全一对一地映射到微服务。因此,应该将多个相关的聚合合并在一起来划分限界上下文。有界上下文可以只包含一个聚合或多个聚合。那么子域和限界上下文是什么关系呢?一般来说,子域和限界上下文之间存在对应关系,但子域本身也可能将多个限界上下文组合起来形成一个大的子域。但无论如何。每个人都应该意识到微服务不能被分割成单独的聚合体。真正的问题不是聚合,而是如何将多个聚合划分到一个有界上下文中。问题的关键——如何将多个聚合划分为一个上下文或子域。我在做企业IT架构规划的时候,在做业务架构规划的时候经常会遇到业务域划分的问题。一种常用的方法是参考行业中常用的模型。比如供应链领域有一个标准的Scor模型可以参考。整个企业的完整业务也可以参考价值链模型。如果你是做电信行业的项目,有一个标准的eTom模型可以参考。产品开发完全可以参考IPD模型。因此,参考行业标准模型是划分业务领域的常用方法。其次,IT人员在做架构时一定不能脱离企业真实的业务组织架构和业务运作。还是以采购业务为例,一个小公司只有一个部门,就是供应链部门,会把所有的招投标、供应商管理、采购询价、采购、采购执行、库存管理等一系列的事情都收起来。但对于大型集团企业来说,招投标、采购、物流、供应商管理等往往是独立的部门。至少它是一个独立的部门。为什么要观察企业自身的业务组织划分?让我们实际观察一下,您就会发现。以某企业为例,这家企业的采购部门可能经常开会或发生争吵,但采购部门和招投标部门往往是招标结果信息的传递。即企业在划分业务部门或组织时,考虑的是如何减少跨部门的交互接口。这与微服务拆分中的微服务要尽可能解耦的道理是一样的。所以回到如何进一步对多个聚合进行分类的问题也是一样的。当你观察时,你会发现供应商和物料的管理实际上是由同一个基础数据管理部门完成的。然后可以将这两个聚合划分为有界上下文。同样,请购单、采购订单、采购执行都是一个部门做的,所以也可以归为一个上下文。当然,你可以从一个完整的业务流程分析入手,看看它分为哪些主要的阶段。一般来说,这些阶段点可以作为微服务划分的边界点。重新聚合通常比简单的事件风暴更有效。例如电商的核心业务场景和订单生命周期如下。当你梳理核心领域对象的生命周期阶段时,你其实可以清楚地识别关键上下文边界和关键领域对象。比如上图中,可以看到商品、订单、供应商、用户、库存都是关键的领域对象,相关的业务操作也是围绕这些业务对象进行的。进一步思考,从聚合到context和subdomains说到这里,一个新的谜题自然而然地产生了。即利用传统的行业参考模型、大的业务流程阶段边界,或者企业自身的业务组织划分来划分微服务。这样划分的微服务粒度比较合适,更容易满足高内聚和松耦合的要求。需要。那么为什么要用领域建模来划分微服务呢?所以,从聚合到上下文,这个逻辑在技术上怎么走就成了问题的关键。也就是说,各种聚合之间仍然存在耦合。我如何分析哪些聚合应该进一步分类到有界上下文中?这个有技术分析方法吗?在这里说说我个人的一些想法。基于核心业务活动的聚合核心业务活动一般是指最终带来明确业务价值的活动。例如,采购订单是核心业务活动,而采购申请、框架协议等是辅助活动或前导活动,最终目的是形成可执行的采购订单。支付是核心业务活动,支付应用是辅助活动,最终服务于支付。基于这种思想,可以围绕核心业务活动的多个聚合,对许多辅助业务活动、支持活动等进行分类,形成上下文边界。基于上层业务对底层聚合之间耦合的分析,以供应商和物料这两个聚合为例。为什么建议将它们放在上下文和微服务中。如上图所示,在分析业务场景时,会发现对于其他聚合根和供应商,物料之间的依赖不是点对点的依赖,而是需要供应商和物料的聚合信息。供应商和材料这两个对象没有耦合。那时,上层的业务场景使两个对象产生了明显的耦合。在这种情况下,它需要划分为有界上下文。由于在一个上下文中,后续的微服务划分对应一个数据库,自然减少了上层调用多个API接口服务后的应用层组装操作。希望以上两种思路在划分上下文边界时对大家有所帮助。再次,将本文要讲解的一些重点总结如下。1.微服务设计到功能和数据层次的划分2.事件风暴到聚合,如何将多个聚合划分到一个上下文中是一个难点3.基于核心业务活动,聚合之间耦合是一种常用的方法当然,这文章还有很多地方没有考虑和完善。欢迎大家提出不同的意见,进一步讨论,以便我以后进一步优化完善微服务分工的思路。