全球架构师峰会 Arch Summit 2018

松耦合无界零售系统搭建之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. 按业务划分限界 上下文 哪些部分应用了DDD Android! App! iOS ! APP! BFF模式 ⼩小程序! WEBAPP! OPENAPI! JSF JSF JSF 服务1! 第三⽅方! HTTPS HTTPS Gateway! 微服务模式 浏览器器! JSF MQ 基础设施! 服务2! JSF 服务n! 第三⽅方服务!
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! 领域间的协作关系 U 表示 “上游”(Upstream), D 表示 ”下游”(Downstream)! WMS! 插件! 技术实现保障上游和下游解耦 • • 依赖代表的是对知 识的理解 区分模块耦合和组 件耦合 只有单向依赖 可以结合整洁架构 的Entity和 UseCase理解
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! DDD适应度! MyBatis/JDBC! 团队适应度! 各种ORM对DDD的适配度 聚合根 非聚合根 聚合根和引用 支持DDD语义的SpringData JDBC
23. 总结 • 边界,边界,边界 • 定义边界间的关系 • 概念不要穿透边界

相关幻灯片