鸡汤一碗
总有一天你的棱角会被世界磨平,你会拔掉身上的刺,你会学着对讨厌的人微笑,你会变成一个不动声色的人
目录
1. DDD 与 微服务
2. 战略设计
3. 战术设计
4. 架构
内容
在解决复杂的问题时候,比较成熟的理论基础是分而治之,逐个击破;所谓“分而治之” 就是把一个复杂的问题按一定的“分解”方法分为等价的规模较小的若干部分,然后逐个解决,分别找出各部分的解,把各部分的解组成整个问题的解 ;
现代复杂的软件系统中, 一个大而全的单体应用,随着业务功能的增加,系统慢慢变得臃肿且难以维护。一个业务需求的响应时间随着系统复杂度的增加而耗时越来越长,且质量也不稳定。那系统怎么才能耗时更短、质量更好地实现业务需要求? DDD + 微服务 。
1. DDD 与 微服务
- 微服务是什么?
微服务是一种松散耦合的分布式架构框架。可将应用拆分成多个核心功能;每个核心功能可单独部署;每个服务都有自己的数据库和模型;通过REST api, 事件流和消息流相互通讯;
- 微服务能解决什么问题?
单体应用扩展性和伸缩能力不足;易部署、易访问、更开放;
- 实施微服务遇到的挑战?
微服务的颗粒度有多大? 微服务如何拆分和设计?微服务的边界如何划分? 这些问题, DDD 可以解决 ;
DDD 与 微服务的关系 ?
面对复杂问题,解决办法通常是拆分,模块化,化整为零。领域驱动设计是面向业务,对业务领域的划分和整合,是逻辑层面。微服务是面向物理落地,是对应用的物理形态进行拆分和整合。从软件工程过程角度看,DDD的战略设计输出物,领域模型及划分的区域,是微服务的输入,一个领域对应一个微服务,微服务运行框架、平台可以承载所有的微服务,提供微服务统一的运行框架,也就是承载所有的业务领域。可见领域驱动与微服务是在软件不同阶段使用的工具,技术或方法论,围绕一个共同的目标,搭建企业业务中台,企业级业务复用,快速的需求响应能力。DDD战略设计的输出,是微服务的输入。
2. 战略设计
从业务的视角出发,构建业务领域模型,划分领域边界,建立通用语言的界限上下文,界限上下文可作为微服务设计的参考边界。DDD 关注的是在明确的界限上下文构建通用语言的模型。
- 界限上下文
它是语义、语境的边界。DDD 关注的是在明确的界限上下文构建通用语言的模型。微服务本质上等于DDD的界限上下文。 只有经过“仅限核心”的严格过滤之后保留下来的概念才能成为拥有界限上下文的 通用语言一部分。
- 子域
子域分为核心子域(组织中最有价值的项目)、支撑子域(非关键,可外包)、通用子域(非关键,可购买); 界限上下文与子域是一一对应的关系;
- 上下文映射
在敏捷管理的项目中,核心域必须和其它界限上下文进行集成,这种关系成为上下文映射; 界限上下文之间的集成可通过REST api, RPC, 异步消息;
3. 战术设计
从技术的视角出发,侧重于领域模型的技术实现,完成技术的开发和落地。包括:实体、值对象、聚合、领域服务、基础设施、应用服务和资源库等代码逻辑设计和实现;
- 聚合
实体? 值对象? 聚合?
一个实体是一个独立的事物。每个实体都有唯一标识;
值对象是一个不变的概念整体所建立的模型;
聚合:由多个实体和值对象组成;每个聚合的根实体控制着所有聚集在其中的元素;
每个聚合都会形成保证事务一致性的边界;
接下来我们要思考的是聚合设计的四条基本规则[1]:
● 在聚合边界内保护业务规则不变性。
● 聚合要设计得小巧。
● 只能通过标识符引用其他聚合。
● 使用最终一致性更新其他聚合。
- 领域事件
领域事件是一条记录,记录着在限界上下文(BoundedContext)中发生的对业务产生重要影响的事情。
领域事件采用事件驱动架构的方式进行解耦,领域事件发布后,事件发布方不必关心订阅方的事件处理是否成功。与采用同步服务调用实现数据一致性不同,领域事件一般都会结合中间件和事件发布订阅异步处理,最终实现数据一致性。
(聚合是微服务最小的业务单元;在边界之外使用最终一致性)
由于战术设计的不懈努力,领域事件在领域模型中落实,并且可以在自己的或者其他限界上下文中被发布和消费。这是一种非常有效的方式,它将已发生的重要事件告知感兴趣的监听器。接下来将学习如何建立领域事件模型以及如何在限界上下文中使用它们。
事件溯源(Event Sourcing)可以描述为,对所有发生在聚合实例上的领域事件进行持久化,把它们当作对聚合实例变化的记录。你存储的是发生在聚合上的所有独立事件,而不是把聚合状态作为一个整体进行持久化。
4. 架构
应用架构
包结构
在DDD 中有一个很棒的解耦设计思想—— 防腐层(Anti-Corruption ),简单说,就是应用不要直接依赖外域的信息,要把外域的信息转换成自己领域上下文(Context )的实体再去使用,从而实现本域和外部依赖的解耦。
在COLA 中,我们把AC 这个概念进行了泛化,将数据库、搜索引擎等数据存储都列为外部依赖的范畴。 利用依赖倒置,统一使用gateway来实现业务领域和外部依赖的解耦。
举个例子,假如有一个电商系统,对于下单这个操作,它需要联动订单服务、商品服务、库存服务、营销服务等多个系统才能完成。
那么在订单域,该如何获取商品和库存信息呢?最直接的方式,无外乎就是RPC 调用商品和库存服务,拿到DTO 直接使用就完了。
然而,商品域吐出的是一个大而全的DTO (可能包含几十个字段),而在下单这个阶段,订单所需要的可能只是其中几个字段而已。更合适的做法,应该是在订单域中,使用gateway 对商品域和库存域的依赖进行解耦。
记忆图