松耦合无界零售系统搭建之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. 总结
• 边界,边界,边界
• 定义边界间的关系
• 概念不要穿透边界
24.