近几年,许多大型企业想要从ERP转变为业务中台。但在落实业务中台时往往对如何设计和划分中台微服务存在一些疑虑,这里也把个人方法总结和大家探讨。
ERP属于集中式架构,所有功能、数据库等都在一个系统的边界范围内。
业务中台属于分布式架构。将功能和数据按领域边界拆分为多个”系统“,有明显的边界之分。
因此两者的差异,不仅体现在系统设计上,更重要的是在思维上的转变,基于业务中台构建的上层应用依靠多个业务中台的领域提供服务来组合,而不是像ERP那样后端仅有一个系统。
业务中台的系统实现由多个微服务组成,每个微服务提供能力的多少、大小由“领域”决定,因此领域划分的结果决定了微服务的边界。
合适的领域划分可以帮助微服务实现高内聚、低耦合的目标,具备良好的扩展性和弹性。
划分业务中台领域的方法不止一种,为什么要选择DDD?
中台的系统落地可以采用微服务架构。微服务是目前公认的业务中台技术最佳实现,可以有效提升业务扩展能力,实现业务能力复用。 微服务的划分方法有多种,没有标准答案。根据实践,按照DDD方法设计出的微服务的业务和应用边界都非常合理,可以很好地实现微服务内部和外部的”高内聚、低耦合“。于是越来越多的人开始把DDD作为微服务设计的指导思想。
2004年,Eirc Evans 发表《领域驱动设计:Domain-Driven Design - Tackling Complexity in the Heart of Software》一书(简称DDD),核心思想是通过领域驱动设计方法定义领域模型,从而确定业务和应用边界,保证业务模型和代码模型的一致性。
我们先要明确运用DDD的目标是将ERP这个集中式系统逐步解耦成多个微服务组成的业务中台。
实现这一目标的方法也不止一种。这里我把自己的经验总结如下:
完成上述目标,分为三步
原则:围绕业务领域职责的完整性做拆分,此阶段应避免拆分过细导致跨微服务的频繁调用。
方法:以限界上下文概念初步划分领域边界
产出:拆分为多个领域
限界上下文(bounded-context):直译为以语义为边界。
1、作用:以限界上文下作为领域边界。这个边界定义了业务模型的范围,使团队所有成员能够明确知道什么应该在模型中实现,什么不应该在模型中实现。
2、如何理解限界上下文?
这是学习DDD的人都比较模糊的概念。对照概念,我们应该理解两个关键词,①边界②语义
①边界:限界上下文的“界”,其实可以理解为模型的边界,系统的边界。例如订单领域应该包含哪些内容,就是这个边界决定的,那么判断边界的依据是什么?是语义。
②语义:在书中叫做“通用语言”:准确描述业务涵义和规则的语言。目的是统一业务语言,明确建模的范围。
例如:订单的支付、履约这些业务,同属交易环节,那么应该在同一“交易”的限界上下文中。而财务的净现值、现金帐等都属于财务范畴,那么应该在同一“财务”的限界上下文中。
ERP到中台领域划分有一个天然的“上下文”的依据就是模块,可以作为初始划分的依据。如销售模块、采购模块、库存模块等。
也可以依据行业经验或案例来参考,如阿里的中台领域划分。
4.2、子域拆分
方法:依据DDD理论,从领域中找出业务实体、值对象,识别出聚合和聚合根
产出:将领域逐步拆分到子域
业务实体:有唯一标识符且标识符在历经各种状态变更后仍能保持一致。实体是多个属性、操作或行为的载体。对象模型建模多围绕实体展开。例如:订单领域的业务实体是销售订单,拥有唯一标识符“订单号”,且无论订单状态如何变化都保持一致。订单域的收款、发货等行为均以订单为载体。
值对象:实体的属性集合(可以引用实体)。最常见就是做附加业务信息的数据冗余。
实体与值对象的区别:实体和值对象的辨别必须放在上下文中。例如:商品在商品域就是业务实体,需要按唯一标识(SKU)来管理,商品域的上下架、价格策略都是依据SKU来执行。而商品在订单域是值对象,因为在订单上下文中,商品仅作为订单的交易货品,不会围绕商品来建模。
聚合:让实体和值对象协同工作的组织。它用来确保这些业务实体在实现共同的业务逻辑时,能保证数据的一致性。
聚合根:是聚合中的实体,是聚合对外的接口人,任何对聚合中的数据访问都需要通过访问聚合根来操作。聚合根是聚合的管理者,也是根实体。一个聚合只有一个聚合根。判断聚合根的方法:聚合根可以用来创建和修改聚合中的其他对象,例如:订单域外系统想要查询订单中的商品,则必须以订单号作为接口入参查询订单中商品信息。
这里仅以销售领域作为做简单示例
4.3、微服务边界
方法:评估聚合间的内聚度、耦合度;并从技术、组织等方面再评估出微服务颗粒度
产出:从子域获得微服务边界
例一。电商业务中,订单域经常有高并发、高读写的业务场景(如双11大促、秒杀活动等),如果仅采用水平扩容的方式付出很高的成本也很难满足性能需求,因此我们采用读写分离策略,将订单拆分了订单的交易执行、订单的查询两个微服务。(当然这也带来了数据一致性的成本问题)
例二。系统中经常会有一些币种、单位、地址等基础数据,如果按上述方法拆分为,可能会得到多个子域。如果每个都是一个微服务,那么运维的成本会比较高。现实中我们往往根据康威定律,将其合并成基础数据微服务,由一个团队来进行维护。
4.4、微服务的迭代
按照上述步骤,我们会逐步将一个集中式系统分解成业务中台的微服务。
但在实际操作中,往往存在边界模糊、重叠的问题,划分的过程往往难以一步到位。
我们可以使用上述方法再次检查,进一步明确业务需求和定义,最终得到一个比较合理的结果。
这个结果其实也不是一成不变的。随着业务的发展等因素,微服务也需要定时检视其合理性,那时我们可以继续使用方法去检验。
《领域驱动设计——软件核心复杂性应对之道 Domain-Driven Design——Tackling Complexity in the Heart of Software》——Eirc Evans
《SOA实践指南》——Nicolai.M.Josuttis.
《微服务设计》——Sam Newman
《DDD实战课》——欧创新