1. DDD 落地与微服务拆分原则
在基于 DDD 的微服务架构中,服务拆分的核心不是技术层,而是业务边界。绝不能按照技术分层(Application / Domain / Infrastructure)来拆分微服务。这种拆分方式会导致业务调用被迫跨服务完成,最终形成低效的分布式单体,并引入严重的网络延迟、事务一致性和系统复杂度问题。
a. 拆分的核心原则:限界上下文(Bounded Context)
- 限界上下文是业务语义一致性的边界
- 一个限界上下文通常对应一个独立的业务能力
- 微服务应围绕限界上下文进行拆分,而非围绕技术层
限界上下文是微服务拆分的逻辑依据,而非代码结构本身
b. 微服务内部仍采用分层架构
在单个微服务(限界上下文)内部,依然遵循清晰的分层设计:
- Application Service:流程编排、用例驱动
- Domain Service / Entity / Aggregate:业务规则与核心模型
- Infrastructure:技术实现细节(DB、MQ、RPC)
分层是服务内部的设计手段,而不是服务拆分的依据
c. 拆分策略:宁大勿小,演进式拆分
- 初期应优先保证业务内聚,避免过度拆分
- 微服务拆分成本高,而合并成本更高
- 可以先在单体中通过限界上下文进行清晰的模块隔离,再逐步演进为独立服务
拆分应该是架构演进的结果,而不是一开始的目标
2. DDD Factory 是领域模型的“守门人”
Factory 的职责不是“替代 new”,而是“保证领域对象诞生即正确”。再狠一点说:如果一个校验不在 Factory 或 Entity 中,那你其实是在允许系统中存在“非法对象”。Factory 不负责“业务流程”,Factory 只负责**“构造一个符合领域不变式(Invariant)的对象”**。
与“对象合法性直接相关的业务校验”可以、也应该放在 Factory 中。
与“业务流程、决策、跨聚合规则”相关的校验,不应该放在 Factory 中。
Factory 不应该负责跨聚合的业务校验,例如:- 校验用户是否被冻结 - 校验库存是否充足 - 校验是否已存在未支付订单
这些都 依赖外部系统或其他聚合状态。 这不是“对象是否能存在”,而是“此时此刻是否允许这么做”。结论:不属于 Factory。
3. 调用别的服务的接口,比如调用dubbo接口,DIP依赖倒置
应该在领域层下定义一个防腐层ACL,放接口,使用当前服务的业务术语定义。
infra层实现接口,调用具体的接口。
接口定义:领域层
是否调用,调用顺序:应用层
技术调用实现:基础设施层
调用本身是否是业务规则:取决于语义
4. 怎么看DDD是否成功
首先从人脑信息输入和处理信息看,感官输入:1Gbps;有意识思考:10bps。差距相当巨大。引出7+-2原则,人的短时记忆一次处理5-9个信息元。所以说DDD并不能让人脑处理复杂度的能力提升,而是为了给人类大脑打补丁。
屏蔽胜过处理:计算机通过增加频率、核心处理复杂度。而人类大脑必须通过忽略处理复杂度。DDD就是一套忽略规则。上层不需知道下层细节。减少了大脑需要实时渲染的信息量。降低认负荷,分离关注点。让大脑可以切单线程模式。软件复杂性不是被“解决”的,而是被“隔离”的。DDD,就是隔离复杂性的工程化方法。
优秀的架构师,本质上不是性能优化专家,也不是技术堆叠专家,而是“认知负荷管理专家”。他通过整洁代码、设计模式、DDD 战略建模,刻意营造一个环境,让人类大脑那可怜的 ~10bps 意识带宽,还能在持续膨胀的系统复杂度中勉强运转。顺着这个逻辑,会自然推出一个残酷结论:如果 DDD 不能明显降低开发者的即时认知负荷,那它就是失败的 DDD。任何增加“脑内跳转成本”的设计,都是反 DDD 的。
5. @ThriftField(requiredness=REQUIRED)
该字段在 Thrift 协议层面是“强制存在的字段”,序列化时必须写出,反序列化时必须读到。只要使用 REQUIRED,你就基本放弃了协议的向前 / 向后兼容性。
99% 的业务字段,不应该用 REQUIRED。REQUIRED 不是“更严谨”,而是“把演进成本提前透支”。在分布式系统里,它几乎总是错误的选择。
6. JDK21虚拟线程
JDK 21 的虚拟线程之所以“快”,不是因为单次执行更快,而是因为“阻塞的成本被从 OS 层降维到了 JVM 层”。
虚拟线程解决的不是 CPU 计算慢,而是 “等 I/O 时浪费太贵”。虚拟线程 ≠ 更快的 OS 线程,虚拟线程是:JVM 管理的用户态线程(User-mode Thread)。
OS 线程(平台线程)的硬成本
传统 Java 线程 = 操作系统线程(1:1 映射)
代价包括:
- 线程栈内存:默认 ~1MB / 线程
- 上下文切换:内核态 ↔ 用户态
- 调度权在 OS
结果:
- 几千线程 → 内存压力
- 几万线程 → 调度灾难
- 阻塞 I/O → 线程“空等”
Java 第一次把“并发调度权”从 OS 手里拿回 JVM。虚拟线程的成功级别,达不到 Java 8 Lambda;但它对 Java 服务器端的“结构性影响”,反而更深。