Java微服务拆分必须基于DDD,通过事件风暴与通用语言识别界限上下文,按核心/支撑/通用域差异化落地,严格对齐聚合根与服务边界,杜绝分布式单体。

Java 微服务架构中,服务拆分不能靠技术直觉或数据库表数量来决定,必须回归业务本质。领域驱动设计(DDD)不是可选的理论工具,而是识别服务边界的唯一可靠路径——它把“哪个功能该放在哪个服务里”这个模糊问题,转化为可讨论、可验证、可落地的业务建模过程。
用通用语言和事件风暴定位真实业务边界
不要一上来就画服务图或写接口。先和产品、运营、客服等角色一起做事件风暴:列出系统中所有关键业务事件(如“用户下单”“库存扣减失败”“订单超时取消”),标注触发者、时间、上下游影响。过程中注意同一词汇在不同环节含义是否一致。比如“客户”在注册流程中是手机号+验证码,在售后流程中可能关联多个历史订单和投诉记录——语义分裂处,就是界限上下文的天然分界线。
- 每个被确认的界限上下文,对应一个微服务的候选范围
- 上下文内所有实体、值对象、聚合根必须使用统一术语,命名直接反映业务说法(如
OrderConfirmedEvent,而非NotifyOrderSuccess) - 跨上下文的数据传递必须经过显式转换,禁止共享JPA实体或DTO复用
按子域类型决定服务粒度与实现深度
不是所有业务都值得独立成服务。DDD将业务划分为核心域、支撑域、通用域,这直接影响Java服务的构建方式:
- 核心域(如电商的“订单生命周期”):必须独立服务,拥有完整数据库、领域模型、防腐层,用Spring Boot + JPA + Domain Events实现强一致性逻辑
- 支撑域(如“优惠券发放”):可独立服务,但允许简化事务处理,例如用最终一致性+消息重试替代两阶段提交
- 通用域(如“文件上传”“短信发送”):优先采用SaaS方案或轻量SDK集成,不自建服务;若必须内置,应封装为内部组件,不暴露为远程API
通过聚合根和限界上下文约束服务职责
一个Java微服务的代码边界,应该严格对齐一个限界上下文,并围绕1–2个核心聚合根组织。以订单服务为例:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
立即学习“Java免费学习笔记(深入)”;
- 聚合根是
Order,其下包含OrderItemShippingAddress等强一致性子实体 - 服务内只操作订单相关表,不碰用户资料表或商品主数据表
- 需要用户信息时,调用
UserClient获取脱敏DTO(如SimpleUserDTO),而非JOIN查询 - 所有对外接口返回的DTO,字段名与上下文通用语言一致(如用
orderStatus,不用statusCd)
避免分布式单体的三个技术红线
即使用了DDD,Java工程落地时仍容易滑向“分布式单体”。以下行为一旦出现,说明拆分已失效:
- 一个HTTP请求需串行调用≥4个服务,且任意一个失败即整体失败
- 多个服务共用同一套MyBatis Mapper XML或共享
@Entity类 - 日志中频繁出现
Caused by: org.springframework.web.client.HttpServerErrorException: 500,且错误堆栈横跨多个服务模块
此时应回退到事件风暴,重新审视上下文映射关系,补全防腐层或改用异步事件解耦。


















