CI/CD流水线性能优化:从20分钟到5分钟的实战

m
marvis

问题诊断:你的流水线在哪里浪费时间?

我们团队维护的 Java 微服务 CI/CD 流水线,平均耗时 20 分钟。通过分析 Jenkins 构建日志,发现时间分布如下:

阶段原耗时占比
依赖下载 (Maven)4min 30s22.5%
编译2min 10s10.8%
单元测试7min 20s36.7%
集成测试3min 50s19.2%
Docker 构建1min 50s9.2%
其他20s1.7%
优化铁律:先度量,再优化。不要凭直觉猜测瓶颈,通过日志和时序数据分析找到真正的耗时大头。

优化手段一:构建缓存分层

Maven 本地仓库缓存

使用 Jenkins 的 Pipeline 持久化 .m2/repository

pipeline {
  agent any
  options {
    // 跨构建缓存 Maven 本地仓库
    buildDiscarder(logRotator(numToKeepStr: '10'))
  }
  stages {
    stage('Build') {
      steps {
        // 利用 Jenkins 共享库缓存
        withMaven(mavenLocalRepo: '.repository') {
          sh 'mvn clean package -DskipTests'
        }
      }
    }
  }
}

效果:依赖下载时间从 4min30s → 45s

Docker 层缓存

# 先复制依赖文件,利用 Docker 层缓存
COPY pom.xml .
RUN mvn dependency:go-offline -B
# 再复制源码
COPY src ./src
RUN mvn package -DskipTests

优化手段二:测试并行化

这是收益最大的优化点。将单元测试按模块拆分为 4 个并行 Job:

stage('Parallel Tests') {
  parallel {
    stage('Core Tests') {
      steps { sh 'mvn test -pl core' }
    }
    stage('API Tests') {
      steps { sh 'mvn test -pl api' }
    }
    stage('Service Tests') {
      steps { sh 'mvn test -pl service' }
    }
    stage('Util Tests') {
      steps { sh 'mvn test -pl util' }
    }
  }
}

效果:测试阶段从 7min20s → 2min10s

优化手段三:增量构建

仅对变更模块执行构建,利用 Maven 的 -pl-amd 参数:

# 仅构建变更模块及其依赖模块
CHANGED=$(git diff --name-only HEAD~1 | grep 'src/' | cut -d'/' -f2 | sort -u)
mvn package -pl $(echo $CHANGED | tr ' ' ',') -amd

最终效果

阶段优化前优化后
依赖下载4min30s45s
编译2min10s1min20s
测试11min10s2min10s
Docker1min50s25s
总计~20min~4min40s

总结

CI/CD 优化不是一次性的工作,而是持续迭代的工程实践。核心原则:缓存一切能缓存的,并行一切能并行的,跳过一切能跳过的。每次构建时间缩短,都直接转化为团队的开发效率和幸福感。