背景

美业业务线技术栈与总部长期独立,基建需要单独适配,维护成本较高。作为负责人,在总部推出统一框架后,我主动申请优先对接。

迁移路径清晰:原有 MVC + Spring + Dubbo,切换到 yz-boot。预发环境验证通过,却在上线后出现故障。

现象

线上直接返回 404,且无任何错误日志。预发完全正常。

排查过程

1. 先找环境差异

预发与线上最大的不同,在于中间件 zanpkg 版本与配置。这一点成为后续排查的重要线索。

2. 为什么 404 且无日志?

模拟完整服务调用链后,定位到核心异常:

DubboAnnotationBean → ClasspathBeanDefinitionScanner → 出现 merge bean conflict 异常。

进一步对比发现,isAllowBeanDefinitionOverriding 等参数在扫描注册、加载、初始化阶段的行为存在差异。

更关键的是:异常为什么没有抛出来?

根因是 Dubbo 本身的一个 bug——DubboAnnotationBean 对异常的错误处理逻辑有缺陷,导致异常被静默吞掉,既无日志,也无明确报错。我们已向官方提交 bug。

3. 为什么最终表现为 404?

最初怀疑是父子容器问题,但 Spring Boot 本身只有单一容器,排除了容器隔离干扰。

真正原因是配置错误叠加:

  • Dubbo 扫描范围过大
  • @ComponentScan 在 Boot 侧扫描范围过小

两者冲突,导致部分 Bean 未能正确注册,最终表现为 404。

根因总结

这次故障是三层问题叠加的结果:

  1. 环境中间件差异(预发 vs 线上)
  2. Dubbo 框架自身 bug(异常被吞,无日志)
  3. 配置错误(扫描范围不一致)

单独看任何一点,都不足以直接导致线上故障;叠加之后,排查难度显著上升。

认知升级

这次故障让我对「架构」和「知识体系」有了更清晰的认识。

1. 架构认知:抽象结构、固化流程、统一变化

真正好的架构,不是堆技术,而是:

  • 抽象出稳定的结构
  • 把变更路径固化成可重复的流程
  • 用统一的方式管理变化

独立技术栈的高成本,本质上是「变化没有被统一管理」的代价。

2. 知识体系化:从结果倒推问题的演进

架构不是凭空设计出来的,而是「问题 + 模式」逐步演进的结果。

做知识体系化时,更有效的方式是:

倒推结果 → 还原问题是如何发展的 → 再提炼可复用的模式。

而不是只记「最终方案是什么」。

总结

统一技术栈的价值,不在于「用同一套框架」,而在于降低长期适配成本、提升变更可控性。

但统一过程本身,往往是暴露历史债务与框架边界的最佳时机。

技术决策与故障复盘的本质,都是在不确定性中,持续把隐性成本显性化。