一、引言
在DDD系列的上一篇中,我们深入探讨了领域与限界上下文这对战略核心概念,理解了如何通过通用语言和上下文地图来划分业务边界。但理论再好,也需要实践的检验。
本文,我们将走进一个真实的系统——GenSI(服务接入系统),看看它如何运用DDD思想完成了一次看似“倒退”、实则“进化”的架构改造:从微服务架构降级到了单体架构。
这听起来似乎与当前“万物皆微服务”的潮流背道而驰,但改造后的效果却令人深思:整体代码结构更加清晰,维护成本大幅下降,扩展性反而更强。这是为什么?DDD在其中扮演了什么角色?让我们一探究竟。
二、GenSI改造前:微服务架构下的混沌
GenSI改造前的架构示意图:

改造前,GenSI采用典型的微服务架构,包含多个独立的服务模块(具体模块请参考图示)。各个模块独立开发、独立部署,服务之间通过RESTful API或消息队列通信。表面上看,这符合微服务的一切“优点”。然而,随着业务发展,问题逐渐暴露:
-
服务边界模糊:各模块之间频繁互相调用,形成网状依赖;
-
领域模型泄露:一个模块中的核心概念被其他模块直接引用,导致概念污染;
-
修改成本高昂:一个简单的字段变更,往往需要修改多个服务并协调上线;
-
测试困难:端到端测试需要启动所有依赖服务,集成测试环境臃肿不堪。
根本原因:微服务拆分是技术驱动的(按功能模块拆分),而非业务驱动的(未遵循限界上下文)。
三、GenSI改造后:DDD引导下的“降级”与“升华”
面对上述问题,团队没有选择继续增加服务数量,而是冷静下来重新审视业务边界。他们运用DDD的战略设计,重新梳理了限界上下文,最终做出了一个大胆的决定:将多个微服务合并为一个单体应用。
改造后的架构示意图:

新的架构呈现为:
-
微核心:一个极轻量的核心模块,负责请求路由、生命周期管理等;
-
多个业务领域模块:每个领域模块对应一个限界上下文(具体模块请参考图示),它们完全独立,只通过核心模块间接交互;
-
明确的依赖方向:所有领域模块依赖核心模块,但领域模块之间零依赖。
这个结构从部署形态上看是“单体”,但从代码组织上看却是高度模块化的“领域内部聚合”。
四、改造后的效果:四个意想不到的好处
1. 结构清晰:包名即业务地图
“每个领域做自己的事情。系统有什么功能看包名就一目了然,不再需要懂Controller代码。”
在改造后的系统中,包结构直接映射限界上下文。新同学接手项目,只需看包名就能快速定位业务模块,而不用像以前一样翻阅几十个微服务的文档。
2. 拒绝老化:微核心 + 服务扩展
“模块之前完整隔离,扩展新服务对核心的服务转发模块没有任何影响。”
核心模块极其稳定,几乎不需要修改。新业务以独立领域模块的形式添加,只要遵循核心定义的扩展点,完全不影响现有模块。这种架构从根本上防止了系统“老化”——业务逻辑不再纠缠在一起。
3. 测试方便:模块可独立测试
“服务模块不需要核心转发模块也能很方便测试。”
每个领域模块都是独立的Java组件,可以脱离核心和外部依赖进行单元测试。对于需要集成测试的场景,也只需启动核心+待测模块,无需启动所有服务。测试效率成倍提升。
4. 架构拆分方便:单体与微服务的平滑切换
“单体架构转微服务,只需修改AsyncBusiService。”
如果未来真的需要将某个领域模块独立部署为微服务,改造点被严格限定在核心模块的异步调用服务(AsyncBusiService)中。领域模块本身不需要任何修改——这正是DDD“限界上下文”隔离带来的红利。
五、小结:DDD的核心价值开始显现
文档第3页的小结值得反复品味:
在这个演示系统中,使用DDD确实给前期设计带来一定的麻烦,但是面对系统后期的核心扩展点——服务集成,还是体现出了不少的优势。而DDD整个架构思想到底好还是不好,还是需要你自己体会。
DDD不是银弹,它不能消灭复杂性,但它能帮我们管理复杂性。前期划分限界上下文、构建通用语言,确实需要投入额外精力,但这份投资会在系统演进过程中持续带来回报。
更重要的是,DDD让我们开始思考一个本质问题:我们的架构,到底是为了什么而存在?
-
是为了追逐技术潮流?
-
还是为了让业务变化更可控、让团队协作更顺畅?
GenSI的改造告诉我们:当技术决策回归业务本质时,哪怕是“逆行”降级到单体,也能获得比盲目微服务更优雅的结果。
六、思考:从演示到实战,你还需要迈过这些坎
文档末尾留下了两个极具启发性的思考题,也是每一位DDD实践者必须面对的挑战:
1. 演示过程中提到好几个对于DDD践行不是很彻底的地方,你想好要如何修正了吗?
在演示中,为了简化,可能还有一些“妥协”:
-
某些领域模块之间是否还存在隐式依赖?
-
核心模块是否承担了过多的职责?
-
值对象是否被设计为不可变?
-
聚合边界是否清晰?
真正的DDD没有“最优解”,只有“持续演进”。 定期审视模型边界,用重构对抗腐化,是DDD实践者的日常。
2. 要提高系统的整体质量,还有很多问题需要考虑,比如服务降级、熔断、事务等等。你可以思考下如何在这个项目中来组织这些业务逻辑。
-
降级与熔断:这些属于基础设施关注点,应放在核心模块的调用层(如AsyncBusiService),而非领域模块内部;
-
分布式事务:如果业务要求跨领域模块的强一致性,需要重新审视限界上下文的划分是否合理。通常,跨上下文的操作应设计为最终一致性,通过领域事件和消息队列实现;
-
业务监控:可以在核心模块中埋点,收集各领域模块的关键指标,而非在业务代码中散落监控逻辑。
这些横切关注点的处理,恰恰是“微核心 + 插件化”架构的优势所在——核心模块可以统一处理非功能需求,领域模块只关心业务逻辑。
七、结语
GenSI的改造故事告诉我们:架构不是目的,而是手段。微服务也好,单体也罢,只要能让业务快速响应变化、让团队高效协作,就是好架构。
DDD的核心思想,正是面向软件的变化进行架构。它让我们不再被技术绑架,而是从业务出发,设计出真正适合自己系统的架构。
网硕互联帮助中心


评论前必须登录!
注册