某互联网公司后端开发工程师陈杰(化名)最近做了一个“小改动”,却引发了一场不小的技术震荡。他用一周时间,将团队的“祖传项目”构建时间从原本的30多分钟压缩到了不到3分钟。领导只是淡淡地说了句“优化了一下”,但随后的连锁反应让他始料未及——隔壁组的生产线CI(持续集成)直接崩溃,整条流水线停摆,隔壁组同事连夜上门求救:“你那配置到底改了啥?”

“祖传项目”的顽疾

这个被团队内部戏称为“祖传项目”的系统,是公司四年前用Spring Boot 1.x搭建的微服务模块。随着业务迭代,代码膨胀到20万行左右,依赖管理混乱,Maven构建脚本中充斥着大量冗余插件。每次提交代码后,CI流水线执行一次构建+测试需要32分钟,严重拖慢了团队开发节奏。

“最痛苦的是调试,等CI等得心慌,看到失败又得重来,一上午就耗在上头。”陈杰回忆道。这样的情况持续了近一年,团队几位同事曾试图优化,但都因为风险太高、优先级低而搁置。

一场“外科手术式”的优化

上个月,陈杰利用项目间歇期,开始系统性调研构建瓶颈。他首先用 mvn clean install -X 开启调试日志,发现Maven的依赖解析环节耗时最长,超过15分钟。项目中存在大量传递性依赖冲突,Maven反复尝试解析版本,甚至出现了几十次重复下载同一jar包的情况。

他的优化策略分三步走:
第一步,清理冗余依赖,利用dependency:analyze插件揪出未使用的jar包,删除无意义的传递依赖声明,将依赖树从层级减少到平铺。
第二步,升级Maven构建配置,启用并行构建(-T 4)和增量编译(-am),同时为关键插件指定版本,避免反复解析元数据。
第三步,引入构建缓存。利用maven-build-cache扩展,将编译产物缓存到共享存储中,避免每次重新编译未改变模块。

优化后,本地构建时间从30分钟降至2分58秒。CI流水线上,由于去掉了大量网络请求和重复编译,构建也缩短至3分半左右。

领导的“轻描淡写”与隔壁组的崩塌

陈杰将优化结果提交到代码仓库,并在合并请求中详细描述了改动。他的直属领导在评审时只留下一句评论:“嗯,看起来是优化了一下构建配置,没什么风险,合并吧。”

然而,问题出现在第二天。隔壁组的CI流水线全线警报——该组依赖的公共服务模块刚好与陈杰的“祖传项目”有共享依赖。陈杰删除了部分公共依赖后,隔壁组的构建脚本无法解析版本,直接抛出“Could not find artifact”错误,全线CI卡死。

隔壁组组长一开始以为是自己的问题,排查了三个小时无果。最后发现,陈杰在优化时调整了核心依赖的版本范围和精简了传递依赖声明,但未在共享的父POM中同步更新。隔壁组的CI引用了旧版依赖管理配置,导致Maven解析时找不到对应版本。

“我当时也懵了,没想到改自己项目的构建,能影响到隔壁组的CI。”陈杰尴尬地解释。最后,他花了半天时间与隔壁组沟通,修改了共享POM的依赖版本策略,并引入Maven BOM(Bill of Materials)统一管理版本号,问题才得以解决。

教训与启示

事后,陈杰在内部技术分享中总结了三点经验:
1. 优化前必须先摸清依赖网络——不是所有依赖都可以“随意”删除,尤其是被其他项目共享的内部库。
2. 公共配置必须统一管理——使用BOM或父POM统一传递依赖版本,避免“各管各的”。
3. 变更一定要通知依赖方——哪怕是一个“小优化”,也可能引发下游的连锁反应。

这场“砍掉90%构建时间”的优化,最终被领导写进了季度绩效亮点,而隔壁组因为这次教训也启动了全面的依赖梳理项目。陈杰感慨:“优化一时爽,上线需谨慎。你以为只是砍了自己的包袱,可能牵着一整个生态。”