我把祖传项目的构建时间砍了90%,领导以为我只是在"优化了一下",结果隔壁组的CI都崩了来问我配置(2026-06-30)

那天下午,我像个“变魔术”的

“你改啥了?隔壁CI挂了三个小时,全组都在等。”领导发来一条消息,语气里带着明显的不满。

事情要从上周说起。我负责的那个祖传Java项目,每次构建要跑12分钟。开发流程是这样的:git push → 等12分钟 → 发现少了个分号 → 再等12分钟。到月底,全组平均每天浪费2小时在等构建上。

我决定动手。结果两天后,隔壁组的CI彻底崩了——不是我的项目变快了,而是他们的。因为我把一份个人配置分享到了内部文档,隔壁组照着改,结果依赖全爆了。

90%是怎么砍下来的?先算一笔账

数据说话:

第一步:干掉最笨的“全量编译”

祖传项目最让人头疼的是:无论改了哪里,mvn clean install 都会把整个项目重新编译一遍。一个Spring Boot微服务项目,光依赖解析就要跑3分钟。

解决方案:增量编译 + 并行构建

# 原来
mvn clean install

# 现在
mvn compile -T 4 -DskipTests -o

结果:原来每次编译3.5分钟的模块,现在35秒搞定。

第二步:把“缓存”用到极致

CI上最痛苦的是一天跑10次全量测试。我们有两个“脏模块”——公共工具包和基础配置,每次都要重新构建。

操作手法:

效果:CI从11分钟降到2分钟出头。

为什么隔壁组CI崩了?我踩了三个坑

他们照着我的配置改了,结果出问题。复盘发现三个致命点:

坑1:跳过测试不等于不测试

我的配置里写了-DskipTests,隔壁组以为是“跳过所有测试”,结果他们关掉了单元测试,导致业务代码有bug直接上线。

正确做法: 使用-Dmaven.test.skip=true只跳过测试执行,但保留测试编译。或者用-Dtest=*IT*只跑集成测试。

坑2:缓存清理策略不一致

他们用了我的本地缓存配置,但忘记设置过期策略。CI跑了一周,缓存里混了不同分支的依赖,导致版本冲突。

建议: 设置maven-dependency-plugin + maven-clean-plugin定时清理,或者按分支隔离缓存。

坑3:并行编译搞崩了JVM堆内存

我用的-T 8(8线程),他们的机器只有4核,直接OOM(内存溢出),构建失败后还产生大量垃圾日志。

黄金规则: 线程数 = 核数 - 1(留一个给系统),且单线程内存不超过2GB。

给想动手的你:3个实用建议

  1. 从“最痛苦”的模块开始:先做一次构建时间分析,找到耗时最长的模块。用mvn clean install -pl <module> --builder smart做精准定位。

  2. 学会利用“并行”红利:不要把构建任务串行化。如果是Docker构建,用docker buildx的并行模式;如果是NPM,加--parallel参数。

  3. 缓存不是万能药:设置缓存过期时间,每周自动清理一次。我写了个小脚本,每天凌晨4点清理72小时前的缓存。

行动起来

别等到隔壁组CI崩了才学。下周一提个小需求:“优化开发体验,把构建时间砍到2分钟以内”。领导通常不会拒绝这种“省钱”的提议。

我已经把优化后的配置文件打包成了模板,放到了内部GitLab。如果你也想试试,可以去找找组织的dev-tools/templates目录。记住:别直接复制,要根据自己项目的依赖树改参数。


免责声明:本文提供的构建优化方法基于通用技术实践,部分参数(如并发线程数、缓存配置)需根据项目实际硬件资源和依赖结构调整。作者不对因直接套用配置导致的系统故障、数据丢失或CI崩溃负责。建议在测试环境先行验证。所有优化操作前请做好代码备份,并确保团队有回滚方案。