松耦合无界零售系统搭建之DDD和微服务实战

复杂性与规模增长的解决之道
ddd设计实践
ddd和微服务的关系
ddd编码实践

展开查看详情

1.松耦合无界零售系统搭建之 DDD和微服务实战 阎华 京东7FRESH架构师

2.阎华 软件架构师 原京东POP平台架构组架构师,现在负责京东 7FRESH架构部的⼯工作,包括保障7FRESH系统的 整体架构⼀一致性和合理理性 ,有超过15年年软件设计 开发经验,主要关注复杂业务系统的灵活可扩展 架构的设计。!

3.• 复杂性和规模增长的解决之道 • DDD设计实践 • DDD和微服务的关系 • DDD编码实践

4. 7FRESH面临的复杂性挑战 • 线上线下融合,场景多种多样 • 业务深度整合,集成无处不在 • 业态创新活跃,应用随需应变

5.复杂性和规模增长的解决之道 分治! 知识! 抽象!

6.衡量分治的标准 高内聚低耦合 ⾏行行李李⻋车厢! 观光⻋车厢! 普通⻋车厢! “ 每个车厢都要符合承重要求, 行李车厢承重能力要高于其他 车厢,车厢间的连接要牢固且 易于拆卸,有足够的灵活性方 连接! 便转弯 ” “ 大件行李应该单独存放,避免 占用普通车厢中的空间,餐车 应该在整个列车的中间,方便 乘客用餐 ”

7.微服务和DDD • 运行时进程间通信,能够 容错和故障隔离 不同的关注点 • 去中心化管理数据和去中 心化治理 • 服务可以独立的开发、测 设计模型 系统的/解决方案的维度 试、构建、部署按业务组 织全功能团队 • 高内聚低耦合,职责单一 真 实 领 微服务 的 域 / 业 务 的 模 • 关注业务领域,建立边界 维 度 型 并构建通用语言,高效沟 通 • 对业务进行抽象,和业务 专家一起建模 • 尽可能维持代码和业务的 DDD 低表示差异

8. DDD概览 ✔ ✔ ✔ ✔ ✔ ✔ 表示本次演示中药用到的概念 战略 战术 • 关注按领域定义,在限界上下文内形成统一语言,提升业务和技术的沟通效率 • 关注领域设计在落地时和设计模型及实现模型的低差异,减小业务和技术之间的鸿沟

9.• 复杂性和规模增长的解决之道 • DDD设计实践 • DDD和微服务的关系 • DDD编码实践

10.DDD设计实践 按业务划分限界上下⽂文! 消除隐式数据依赖! 明确定义上下游关系! 下游的⾃自我保护!

11.按业务划分限界 上下文 识别业务领域 行业经验 使用工具 从业务能力的角度识别 核心域/支撑域/通用域 ⻔门店! 仓库! ⽣生产加⼯工! 多维度抽象

12.按业务划分限界 BFF模式 Android! App! iOS ! APP! HTTPS ⼩小程序! 浏览器器! HTTPS 第三⽅方! 上下文 Gateway! JSF WEBAPP! JSF OPENAPI! JSF 哪些部分应用了DDD JSF JSF 微服务模式 服务1! 服务2! 服务n! MQ 基础设施! 第三⽅方服务!

13. 消除上下文间的隐式数据依赖 用户上下文 • 跨上下文之间不存在实体引用 • 是否要抽象一个值对象取决于上下文的边 商户上下文 界范围 订单! 购买者! • 关注对象胜于关注表结构 《值对象》! 《值对象》! 交易上下文 明细! 商品! 商品上下文 《实体》 《值对象》 使⽤用微服务架构,服务之间的确在变量量层⾯面做到了了彼此隔 订单上下文 离,然⽽而……任何形式的共享数据⾏行行为都会导致强耦合…… 如果给服务之间传递的数据记录中增加了了⼀一个新字段,那 服务上下文 么每个需要操作这个字段的服务都必须要做出相应的变 更更,服务之间必须对这条数据的解读达成⼀一致,那其实这 些服务全部都是强耦合与这条数据结构的,他们是间接彼 …… 此耦合的。 --《架构整洁之道》!

14. DEMO 订单! 购买者! 《值对象》! 《值对象》! 明细! 商品! 《实体》 《值对象》 订单上下文 订单号! 购买者标识! 购买者类型! 1! zhangsan! 1! 2! apple! 2! T_ORDER 明细标识! 订单号! 商品品标识! 商品类型! 1! 1! 1001! 1! 2! 1! 1001! 2! T_ORDER_ITEM

15. 明确定义依赖方向 在线销售 交易易 ⽣生产 库存 服务 调度 D D D • 依赖代表的是对知 识的理解 MQ监听 远程调⽤用 • 区分模块耦合和组 U 件耦合 U U U U U U • 只有单向依赖 WMS! 插件! 地址 ⽀支付! 商品! 订单! 物料料! WMS! • 可以结合整洁架构 的Entity和 UseCase理解 领域间的协作关系 技术实现保障上游和下游解耦 U 表示 “上游”(Upstream), D 表示 ”下游”(Downstream)!

16. 下游的自我保护 防腐层(Anticorruption Layer):对于下游来说,需要根据⾃自⼰己的领域 模型创建⼀一个单独的层,该层作为上游系统的代理理向你的系统提供功 在线销售 能。它在你⾃自⼰己的模型和他⽅方模型之间进⾏行行翻译转换。! 库存 D 引⼊入防腐层,RPC客户端/SDK的模式相对于REST在开发的易易⽤用性⽅方⾯面 没有明显的优势了了。 ACL MQ监听 远程调⽤用 U WMS! 插件! U 餐饮排班表! U ⻔门店! 用Feign作为REST的客户端,自然生成了防腐层 下游通过防腐层做自我保护 RPC更更易易⽤用……但在分布式环境下,REST ⽅方式的服务依赖要⽐比 RPC 就这个例子,顺便说一下,在面对同类型多上游的情况下, ⽅方式的依赖更更为灵活。 对下游来说,策略模式依然是最好用的自我保护模式,虽然保障 --《微服务设计》! 的是内部架构质量

17.• 复杂性和规模增长的解决之道 • DDD设计实践 • DDD和微服务的关系 • DDD编码实践

18. DDD和微服务的关系 • 逻辑划分是否要演变为物理隔离? • 系统架构的逻辑划分可以细于部署 单元的物理隔离 • 反思和质疑 - Modulithic/ Microservice Envy 系统架构是由系统内部的架构边界,以及边界之间的依赖关系所定义的, 与系统中个组件之间的调⽤用和通信⽅方式⽆无关 …… 所谓的服务本身只是⼀一种 • 演进式架构 ⽐比函数调⽤用⽅方式成本稍⾼高的,分割应⽤用程序⾏行行为的⼀一种形式,如系统架构 ⽆无关。 --《架构整洁之道》!

19.• 复杂性和规模增长的解决之道 • DDD设计实践 • DDD和微服务的关系 • DDD编码实践

20. 按DDD编码的意义 让代码体现设计,保持⼆二者的低表示差异,难点在于对聚合根 的实现。

21. 聚合根的设计要点 • 聚合根封装其内部实体和值对象, 并保证数据的最终一致性 聚合根封装多个实体 • 一个聚合根一个repository而不是 一个实体一个 • 聚合根之间不能建立关系,只能通 过ID引用 聚合根通过ID引用

22. 聚合根的设计难点 常⽤用ORM框架的⽐比较! 1! 2! 用Mybatis实现Repository SpringDataJDBC! JPA/Hibernate! MyBatis/JDBC! DDD适应度! 团队适应度! 聚合根 非聚合根 各种ORM对DDD的适配度 聚合根和引用 支持DDD语义的SpringData JDBC

23. 总结 • 边界,边界,边界 • 定义边界间的关系 • 概念不要穿透边界

24.