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

做微服务设计为什么需要DDD?_1

时间:2023-03-16 18:35:46 科技观察

记得在规划设计微服务架构的时候,张队长给我的一个提醒我至今记忆犹新:“为什么你的设计蓝图中没有看到DDD的影子?”随着领域认知的深入,越来越感受到DDD的重要性。但是DDD的内容很多,需要深入了解吗?我觉得没必要入坑太深。个人拙见,其核心点在于针对贫血模型的不足之处进行设计,将原有传统贫血模型中的业务逻辑层进行了处理。出来集成到Domain层,这样面对复杂业务的大规模变更,我们只需要关注Domain即可。回到正题,我们需要了解的是微服务和DDD是什么关系?因为在互联网时代,软件面临的问题域比以前复杂得多。这种复杂性来自不断扩大的问题领域本身。也来自于这种规模增长带来的创新变革和挑战。但是,一个人和一个团队,对复杂事物的认知是有限度的。面对如此复杂的问题,唯一的办法就是分而治之。划分主要考虑的是如何划分;治理是指事业部各部分要能够独立运作,相互配合,完成总体目标,能够应对外部变化的影响。微服务的缺陷微服务架构在分而治之方面提供了很好的理论指导和最佳实践。微服务是解决复杂问题的灵丹妙药吗?事实上,并非如此。许多团队都在应用微服务。他们用服务架构搭建了自己的系统后,发现这个复杂性问题并没有完全解决,甚至还带来了一些其他的问题。例如,服务并没有解决复杂系统如何响应不断变化的需求的问题,甚至加剧了这个问题。当需求发生变化时,需要花费大量精力来确定哪些微服务受到此变化的影响。这些服务的多个团队需要经过无休止的扯皮来决定哪个服务多哪个服务少去改,然后测试团队还需要做昂贵的联调测试。即便如此,开发组还是心有余悸,不得不小心翼翼地通过一系列的开关控制进行切流和灰度发布。从业务的角度来看,微服务架构并没有避免这种鸟枪式的修改。这甚至激怒了他。为什么是这样?一个重要的原因是在分纬度上没有综合考虑微服务架构。DDD函数我们在做这类工作的时候,可以参考我的另一篇文章《微服务的拆分姿势》。需要考虑哪些维度?我觉得我们至少需要考虑三个维度:功能纬度,质量纬度,比如性能,可用性工程纬度微服务在第二个上给了很好的指导,在第三个上给了一些建议。然而,对于第一个功能维度只给出了非常有限的指导,这就是为什么领域驱动设计(DDD)随着微服务的流行而被重新强调的原因。DDD弥补了微服务在功能划分方面没有很好指导的缺陷。因此,它们在面对复杂问题和构建系统时是一种“互补”的关系,在系统拆分时又能很好地配合。只是他们看待系统分裂的角度不同。微服务中服务的重点是DDD所提倡的六边形架构中的领域层。拆分案例接下来,结合DDD和微服务来拆分一个复杂的系统。关于领域,我们把企业的业务范围和在该范围内开展的活动称为领域,与软件系统无关。该字段将被划分为多个子域。比如我们的电子商务系统会有:商品子域、订单子域、库存子域等,在不同的子域中,不同的概念有不同的含义。因此,我们在进行领域建模时,必须要有一个明确的领域边界,在DDD中称为boundedcontext,是系统内部的一个架构边界,决定了系统的架构。划分系统内部架构边界的简明方式architecture书中说:“系统架构是由系统内部架构边界和边界之间的依赖关系,以及系统中各个组件之间的通信和调用决定的。”是无关紧要的”。我们常说微服务的服务调用本身只是一种比函数调用稍微贵一点的拆分应用行为的形式,与系统架构无关。因此,复杂系统的划分,首先重要的是划分内部的架构边界,即明确划分上下文以及它们之间的关系,这对应于我们前面提到的功能维度。这就是DDD派上用场的地方。其次,我们考虑如何基于非功能维度来划分,这也是微服务可以发挥优势的地方。比如我们把系统分为三个上下文,ABC和ABC。三个上下文的代码可以运行在一个部署单元中,通过进程内调用完成操作。这是一个典型的单体架构;它们也可以运行在一个独立的部署单元中运行,通过远程调用完成操作。这就是现在流行的微服务架构。界限清晰的好处是我们更多的是两种架构模型的混合体。比如A和B一起是一个部署单元,C是另外一个独立的部署单元。这往往是因为C非常重要,它的并发访问量非常大,或者它的需求变化频繁。拆分C有以下优点:资源倾斜使用弹性设计模式:如重试、断路器、降级使用特殊技术:例如Go语言有独立的代码库:有独立的团队和运维人员,而A和B运行期间的隔离和不干扰这四点正是服务架构所关心的。它是从非功能纬度的角度来看拆分的问题。他关注的不是系统架构的逻辑边界,更关注的是应用行为的分离。那为什么不把A和B拆分成一个独立的部署单元呢?这将带来更多的收益和额外的成本。该体系结构应该能够发展。在业务发展初期,我们要注意系统架构保持逻辑边界清晰,关系正确。随着业务量的增加,逐渐拆分。这是DDD和微服务架构结合应用带来的最大收益。在单体架构中,很难保持架构的逻辑边界不被打破。如果逻辑边界不明确,可能需要拆分服务器时无法拆分。此外,没有人能一下子就正确定义逻辑边界。即使上下文定义不正确,DDD中聚合根的概念也可以保证我们可以演化出更合适的上下文。DDD限界上下文通过实体和值对象对领域概念进行内部建模,一组实体和值子对象属于一个聚合根。根据DDD的要求,聚合根用于保证内部实体规则的正确性和数据的一致性。外部对象只能通过ID引用聚合根,不能引用聚合根内部的实体。聚合根不能共享数据库事务。之间的数据一致性需要通过最终一致性来保证。基于这些约束,未来可以根据需要将聚合根升级为上下文,甚至拆分成微服务,相对容易。