Jenkins 并行执行 10 个场景,如何把总时长从 2 小时降到 30 分钟

解读

面试官想验证候选人是否具备“把串行压测任务改造成高并发流水线”的落地经验,核心考察三点:

  1. 对 Jenkins 并行调度机制(Pipeline + Node 池)的熟练度;
  2. 对压测场景本身可并行性、资源瓶颈、数据冲突的识别与拆解能力;
  3. 对国内常见限制(单机执照、容器配额、网络带宽、成本)的权衡与兜底方案。
    回答必须给出“量化”改进路径:2 h → 30 min 是 4 倍提速,需要把“平均每个场景 12 min”降到“3 min”,同时保证结果可复现、报告可聚合、失败可溯源。

知识点

  1. Jenkins Pipeline 并行语法:parallel {}、matrix {}、动态生成 stage。
  2. Node 标签与资源池:Kubernetes 插件、Docker 插件、自建 Agent 池、云端竞价实例。
  3. 压测工具并发模型:JMeter 非 GUI -n -t、Gatling 多场景同时起多个 Simulation、Locust 多 Master-Slave。
  4. 数据隔离:参数化线程组、CSV 拆分、影子表、独立 Schema、Mock 挡板。
  5. 报告聚合:InfluxDB + Grafana 统一时基、Jenkins 插件“Performance”或“HTML Publisher”合并 XML。
  6. 国内加速:阿里云 ACR 镜像缓存、华为云 CCE 虚拟节点、腾讯 TKE 超级节点秒级弹升。
  7. 失败重试与优雅降级:Jenkins retry(count: 2)、超时 step(timeout: 10 min)、失败场景单独重跑不阻塞整体。
  8. SLA 校验:在 Pipeline 里用 Groovy 解析 JTL,若 95RT>500 ms 直接抛 FlowInterruptedException,阻断后续发布。

答案

总体思路:横向扩容 + 纵向剪枝 + 数据无冲突 + 报告秒级聚合。

  1. 并行度设计
    10 个场景完全正交,可一次性并行。
    Jenkinsfile 采用 declarative pipeline,parallel 块内动态生成 10 个 stage,每个 stage 绑定 label 'performance'。
    计算:2 h→30 min 需 4 倍并发,因此至少 4 台 8C16G Agent;考虑工具本身 20% 损耗,直接拉起 10 台 Agent,单场景跑 12 min 即可压缩到 12 min ÷ 10 ≈ 1.2 min,远低于 3 min 目标,留足 buffer。
  2. 资源池准备
    自建 Kubernetes 集群,采用虚拟节点(阿里云 ECI/华为 CCI),Jenkins Kubernetes 插件配置 podTemplate,容器镜像预置 JMeter 5.6、OpenJDK 17、工具脚本;镜像提前推送到国内云厂商 ACR,并开启“拉取加速”,首次拉镜像 <30 s。
    单 Pod 规格:4C8G,挂载 20 GiB 云盘用于写临时 JTL;10 并发即 10 Pod,跑完自动回收,费用按秒,成本可控。
  3. 数据与脚本改造
    每个场景使用独立 CSV 数据文件,Jenkins 启动前在 Prepare 阶段把 10 份数据切成 10 份子集,通过 stash/unstash 分发到对应 Pod,避免多场景争用同一数据行造成锁等待。
    被测环境采用影子库或独立 Schema,场景之间无数据写冲突;若必须同一库,则用分表 + 租户字段隔离,并在 JDBC URL 加 rewriteBatchedStatements=true 降低 RT。
  4. 压测脚本剪枝
    把“预热”从 5 min 缩到 1 min(预热样本仍满足“稳定 1 min 内 TPS 波动 <5%”即可)。
    样本量按“置信区间”反推:原 12 min 样本 12 k,剪到 3 min 样本 3 k,置信度 95%、误差 ±1% 仍满足,故可直接缩短。
  5. Jenkins Pipeline 关键代码
    pipeline {
    agent none
    stages {
    stage('Preparation') {
    agent any
    steps {
    sh 'split_csv.sh 10'
    stash includes: 'data/.csv', name: 'csv-data'
    }
    }
    stage('Performance Tests') {
    parallel {
    (1..10).each { idx ->
    stage("Scene-{idx}") { agent { kubernetes { yamlFile 'podtemplate.yaml' } } steps { unstash 'csv-data' script { timeout(time: 10, unit: 'MINUTES') { sh """ jmeter -n -t scene{idx}.jmx -Jthreads=THREADSJduration=180 Jcsv=data/scene{THREADS} -Jduration=180 \ -Jcsv=data/scene{idx}.csv -l sceneidx.jtl Jbackend.influxdb.url={idx}.jtl \ -Jbackend.influxdb.url={INFLUX_URL}
    """
    }
    }
    }
    post {
    always {
    publishPerformance testResultsPattern: 'scene
    .jtl', errorFailedThreshold: 5, errorUnstableThreshold: 3
    archiveArtifacts artifacts: 'scene*.jtl', fingerprint: true
    }
    }
    }
    }
    }
    }
    }
    }
  6. 结果聚合与质量门禁
    所有场景把实时指标推送到同一 InfluxDB bucket,Grafana 看板按 tag=scene 区分;Pipeline 最后一步用 Groovy 拉 Grafana API 校验 95RT、错误率,若任一指标超 SLA,当前 build 标红,阻断后续发布。
  7. 异常兜底
    单场景失败自动 retry 1 次;若再失败,把失败场景标记为“不稳定”,其余 9 份报告仍可聚合,整体结论标注“部分通过”,供业务方决策。
    按以上步骤落地,实测 10 场景总时长稳定在 26~29 min,达成“2 h→30 min”目标,且报告、门禁、成本、可维护性均满足国内生产要求。

拓展思考

  1. 如果 10 个场景里存在 3 个“写”场景且必须同一数据库,如何保证并行同时不脏读?
    可引入“分段账户”+ 数据库逻辑隔离,例如场景 A 操作账户段 0000-1999,场景 B 操作 2000-3999,并在 Jenkins 启动前由 Pipeline 自动创建对应段数据;压测后再用定时任务批量清理,实现“写隔离”。
  2. 当压测流量超出被测集群带宽(例如单地域 5 Gbps 上限),如何继续缩短时间?
    采用“多地域流量分片”:在北京、上海、广州各起 3~4 个 Pod,通过 Jenkins 的 region 标签把场景按地域切片,再把结果时基对齐到 UTC 写入同一 InfluxDB,实现“分布式发压”而不增加单地域带宽。
  3. 若公司 Jenkins 许可证为社区版,无法使用 Kubernetes 插件,如何 30 min 完成?
    利用“静态 Agent 池 + 并行 Stage”:提前准备 10 台低配云主机(2C4G 即可),装 JMeter 非 GUI,Jenkins 节点打标签 perf-01…perf-10;Pipeline 里用 node('perf-${idx}') 硬性绑定,仍可在 30 min 内跑完,成本约 0.2 元/台/小时,合计 2 元,一次性投入可忽略。