背景
美业业务线技术栈与总部长期独立,基建需要单独适配,维护成本较高。作为负责人,在总部推出统一框架后,我主动申请优先对接。
迁移路径清晰:原有 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。
根因总结
这次故障是三层问题叠加的结果:
- 环境中间件差异(预发 vs 线上)
- Dubbo 框架自身 bug(异常被吞,无日志)
- 配置错误(扫描范围不一致)
单独看任何一点,都不足以直接导致线上故障;叠加之后,排查难度显著上升。
认知升级
这次故障让我对「架构」和「知识体系」有了更清晰的认识。
1. 架构认知:抽象结构、固化流程、统一变化
真正好的架构,不是堆技术,而是:
- 抽象出稳定的结构
- 把变更路径固化成可重复的流程
- 用统一的方式管理变化
独立技术栈的高成本,本质上是「变化没有被统一管理」的代价。
2. 知识体系化:从结果倒推问题的演进
架构不是凭空设计出来的,而是「问题 + 模式」逐步演进的结果。
做知识体系化时,更有效的方式是:
倒推结果 → 还原问题是如何发展的 → 再提炼可复用的模式。
而不是只记「最终方案是什么」。
总结
统一技术栈的价值,不在于「用同一套框架」,而在于降低长期适配成本、提升变更可控性。
但统一过程本身,往往是暴露历史债务与框架边界的最佳时机。
技术决策与故障复盘的本质,都是在不确定性中,持续把隐性成本显性化。