知识卡片
逻辑边界、物理边界、代码边界的三层对应关系,与逻辑边界不必等于物理边界
内容
DDD设计微服务时会同时形成三类边界。逻辑边界指微服务内不同聚合之间的边界——一个微服务通常包含多个聚合,聚合之间业务高内聚、彼此低耦合,这是一个虚拟边界,主要用来约束业务和代码重组的规则:当业务发生大变化时,业务端可以以聚合为单位重组领域模型,应用端可以以聚合代码目录为单位重构代码。物理边界指微服务之间的边界,从部署和运行的视角定义——不同微服务运行在不同的物理/虚拟环境(如不同JVM)中,能独立开发、测试、构建、部署,为了实现这层解耦,应尽量少用同步服务调用,优先采用领域事件驱动的最终一致性机制。代码边界指微服务内不同职能代码目录之间的边界,因为领域模型和代码模型是映射关系,代码边界会直接体现为业务边界,控制代码重组时的影响范围。三者的关键关系是:逻辑边界不必等于物理边界——聚合虽然是可以独立拆分为微服务的最小业务单元,但不代表每个聚合都必须立刻拆成一个独立微服务;如果团队暂时不具备微服务治理和运维能力,完全可以先用DDD方法把这些聚合的逻辑边界和代码边界划清楚、以单体形式部署,等具备条件后再随时按限界上下文/聚合边界把逻辑边界升级为物理边界,完成向微服务的演进——先把逻辑和代码边界做对,物理边界什么时候拆可以再议。
结构图:
flowchart TB
subgraph Physical["物理边界(部署/运行视角)"]
MS1["微服务A<br/>(独立JVM/独立部署)"]
MS2["微服务B<br/>(独立JVM/独立部署)"]
end
subgraph MS1detail["微服务A内部"]
direction TB
subgraph Logical1["逻辑边界:聚合1"]
Code1["代码边界:聚合1目录<br/>entity/event/service/repository"]
end
subgraph Logical2["逻辑边界:聚合2"]
Code2["代码边界:聚合2目录<br/>entity/event/service/repository"]
end
end
MS1 -.-> MS1detail
MS1 -- "领域事件驱动<br/>最终一致性" --> MS2
Logical1 -. "可独立拆分为<br/>新微服务" .-> MS2
参考来源
- 位置:第16章《如何实现微服务的架构演进》"16.3 微服务边界的作用"、"16.4 正确理解微服务的边界"(源文件:_epub-src/OEBPS/Text/chapter4-5-3.xhtml、chapter4-5-4.xhtml)
- 结论依据:原文说明"逻辑边界主要定义同一业务领域或微服务内,紧密依赖的领域对象所组成的不同聚合之间的边界……物理边界主要是从部署和运行的视角来定义微服务之间的边界……代码边界主要用于微服务内不同职能代码之间的隔离……那么,实施过程是否一定要做到逻辑边界与物理边界一致呢?……答案是不一定,这里要考虑微服务过度拆分的问题……我们甚至可以按照DDD方法将它设计为单体应用",直接支撑本卡片结论。
- 原始内容:逻辑边界主要定义同一业务领域或微服务内,紧密依赖的领域对象所组成的不同聚合之间的边界……物理边界主要是从部署和运行的视角来定义微服务之间的边界……那么,实施过程是否一定要做到逻辑边界与物理边界一致呢?……答案是不一定。