18.3.3 流水线阶段设计与并行/矩阵构建
在流水线设计中,合理拆分阶段(stage)并利用并行与矩阵构建可以显著提升交付效率与可维护性。阶段划分应贴合价值流,从源码到发布形成清晰链路,并在关键节点设置质量门禁。
阶段设计原则#
- 按价值流拆分:Checkout → Build → Unit Test → Integration Test → Package → Security Scan → Deploy → Verify。
- 阶段内聚、职责单一:单个阶段只做一类工作,便于失败定位与重试。
- 可观测性:每阶段输出关键日志、产物与指标,便于追踪。
- 可重用与可扩展:与共享库结合,将通用步骤封装。
- 环境隔离:区分构建、测试、预发与生产环境,避免污染。
并行构建(Parallel)#
并行适用于独立任务,例如多模块构建、分组测试、扫描任务等。
应用场景
- 多模块项目并行构建
- 单元测试与代码扫描并行
- 多环境部署前的并行验证
设计要点
- 资源限制:控制并发避免Agent耗尽
- 失败策略:设置failFast按需快速失败
- 结果汇总:并行分支产物统一归档与报告聚合
示例结构(Declarative)
// Jenkinsfile
pipeline {
agent any
options { timestamps() }
stages {
stage('Test') {
failFast true
parallel {
stage('UnitTest') {
steps {
sh 'mvn -B -DskipITs=false test'
}
}
stage('IntegrationTest') {
steps {
sh 'mvn -B -DskipUTs=true verify'
}
}
stage('SecurityScan') {
steps {
sh 'trivy fs --exit-code 0 --format table .'
}
}
}
}
}
post {
always {
junit 'target/surefire-reports/*.xml'
archiveArtifacts artifacts: 'target/*.jar', fingerprint: true
}
}
}
矩阵构建(Matrix)#
矩阵构建用于多维度组合测试或打包,例如不同JDK、OS、架构或环境组合。
应用场景
- JDK 8/11/17 多版本测试
- Linux/Windows 多平台构建
- 多架构(amd64/arm64)制品构建
设计要点
- 维度控制:避免组合爆炸,合理裁剪矩阵
- 排除规则:通过exclude去除无效组合
- 统一产物命名:包含维度信息,便于追踪
- 资源调度:为不同组合指定合适的Agent标签
示例结构(Declarative)
// Jenkinsfile
pipeline {
agent none
stages {
stage('Matrix Build') {
matrix {
axes {
axis { name 'JDK'; values '8', '11', '17' }
axis { name 'OS'; values 'linux', 'windows' }
}
excludes {
exclude { axis { name 'OS'; values 'windows' }
axis { name 'JDK'; values '8' } }
}
agent { label "${OS}" }
stages {
stage('Build') {
steps {
sh 'echo "Build with JDK=${JDK} on ${OS}"'
sh 'mvn -B -DskipTests package'
}
}
stage('Test') {
steps {
sh 'mvn -B test'
}
}
}
post {
always {
archiveArtifacts artifacts: "target/*-${JDK}-${OS}.jar", allowEmptyArchive: true
}
}
}
}
}
}
并行与矩阵结合策略#
- 先矩阵后并行:适合多维组合后并行执行测试
- 先并行后矩阵:适合按模块并行,再在模块内矩阵测试
- 拆分流水线:复杂场景使用多流水线协作(上游触发)
并行+矩阵示例
// Jenkinsfile
pipeline {
agent none
stages {
stage('Modules') {
parallel {
stage('Module-A') {
stages {
stage('Matrix-A') {
matrix {
axes { axis { name 'JDK'; values '11', '17' } }
agent { label 'linux' }
stages {
stage('Build') { steps { sh 'mvn -pl module-a -am package' } }
}
}
}
}
}
stage('Module-B') {
steps { sh 'mvn -pl module-b -am test' }
}
}
}
}
}
失败与重试策略#
- 关键阶段阻断:构建与测试失败直接阻断
- 非关键阶段降级:扫描或通知失败可标记为UNSTABLE
- 重试控制:对不稳定测试设置
retry次数 - 超时控制:对长耗时阶段设置
timeout
示例
stage('E2E Test') {
options { timeout(time: 20, unit: 'MINUTES') }
steps {
retry(2) {
sh './tests/e2e.sh'
}
}
post {
unsuccessful { currentBuild.result = 'UNSTABLE' }
}
}
产物与报告管理#
- 使用
archiveArtifacts归档产物 - 使用JUnit、Allure等统一测试报告
- 并行/矩阵结果汇总生成统一可视化报告
报告汇总示例
post {
always {
junit 'target/surefire-reports/*.xml'
archiveArtifacts artifacts: 'target/*.jar, reports/**', fingerprint: true
}
}
安装与环境准备示例#
并行与矩阵通常依赖多Agent与标签,以下为基础安装与标签设置示例。
Linux节点安装Java与Maven
# Ubuntu
sudo apt update
sudo apt install -y openjdk-11-jdk maven
# 校验
java -version
mvn -v
Jenkins节点标签设置
- 在 Jenkins 节点配置中添加标签:linux、windows
- 在 Pipeline 中用 agent { label 'linux' } 绑定
Docker化构建可选
# 安装Docker
curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker jenkins
# 验证
docker version
常见排错与定位#
- 并行阶段不执行
- 可能原因:语法嵌套错误或agent none未设置分支agent
- 排查:检查流水线日志,确保每个并行分支有agent或继承agent any - 矩阵组合过多导致排队
- 可能原因:轴值过多、Agent不足
- 排查:减少轴值、增加排除规则,或增加节点与标签 - 归档产物为空
- 可能原因:产物路径与矩阵维度命名不一致
- 排查:在构建后ls -l target验证产物生成 - JDK切换失败
- 可能原因:节点未安装对应JDK
- 排查:在节点执行java -version确认,或使用工具链插件
诊断命令示例
# 查看构建节点信息
uname -a
java -version
mvn -v
# 查看产物目录
ls -lh target/
练习题#
- 将现有单模块流水线改造为并行的
UnitTest与SecurityScan两个阶段,要求失败即中断。 - 设计一个JDK=11/17、OS=linux/windows的矩阵构建,并排除
windows+11组合。 - 在矩阵构建中为不同组合生成命名包含维度信息的产物,例如
app-11-linux.jar。 - 为E2E测试阶段添加
timeout与retry,并在失败后标记为UNSTABLE。 - 将并行分支产物统一归档并生成JUnit报告。