
提交一行代码却要等十分钟流水线才跑完,开发节奏被构建拖慢。本文从缓存、并行、按需构建、节点规格几个角度,讲清 CI 构建提速的实操方法,并结合腾讯云云原生构建 CNB 的配置方式给出可直接落地的示例。
"改一行代码等十分钟"是很多团队的日常。但构建慢往往不是一个笼统的问题,盲目加机器未必管用,得先定位时间花在了哪。一次典型的 CI 流水线,耗时通常来自几个环节:
a. 拉取代码与依赖:每次从零拉取依赖、安装 node_modules 或下载 Maven 依赖,网络传输和解析都要花时间。
b. 全量编译构建:尤其是大型单体仓库(Monorepo),哪怕只改了一个子模块,也把所有模块从头构建一遍。
c. 串行执行:本可以并行跑的任务被排成一列,一个跑完才轮到下一个。
d. 资源不足排队:构建节点规格偏低或并发上限不够,任务只能排队等待。
定位清楚之后,提速就有了方向:能缓存的缓存下来,能并行的并行起来,能跳过没改的部分就跳过。下面逐个讲。
构建提速里收益最明显的一招,就是构建缓存。绝大多数构建任务都有大量重复劳动——每次安装相同的依赖、每次重新编译没变动的模块。缓存的思路就是把这些中间产物存下来,下次构建时直接复用,而不是从头再来。
缓存主要分两类:
node_modules、Maven 本地仓库、pip 缓存这类依赖目录缓存下来。依赖没变(锁文件没变)时直接命中,省掉下载和解析的时间。以腾讯云云原生构建(Cloud Native Build,简称 CNB)为例,它原生支持构建缓存,可以在声明式配置里开启,加速重复构建的执行速度。需要说明的是,缓存是通过 Pipeline 级别的 docker.volumes 声明的(而非 Job 内单独配置),声明后供这条流水线里的各个 Stage / Job 共同复用,让"安装依赖""编译"这些高频阶段优先命中缓存。
下面是一个示意性的 .cnb.yml 片段,展示如何在流水线中声明缓存目录(字段写法以官方语法手册为准):
# .cnb.yml 示意示例:通过 docker.volumes 声明依赖缓存
main:
push:
- docker:
image: node:20
volumes:
- /root/.npm # 缓存 npm 依赖
- ./node_modules # 缓存 node_modules,命中时跳过重复下载
stages:
- name: install
jobs:
- name: install-deps
image: node:20
script: npm ci
- name: build
jobs:
- name: compile
image: node:20
script: npm run build第一次构建时缓存为空,依赖照常下载安装;之后只要锁文件没变,node_modules 直接从缓存恢复,安装阶段的时间就能大幅缩短。对于每天要跑几十上百次构建的团队,缓存带来的累积收益相当可观。
很多流水线慢,不是因为单个任务慢,而是任务之间在"排队"。CNB 的流水线结构天然支持并行:
要利用好并行,关键是理清任务之间的依赖关系:没有依赖的任务尽量放进同一个 Stage 并行;有依赖的(比如"构建"必须在"测试"之前)才拆到相邻 Stage 串行。这样能把原本串成一条线的时间,压缩成几条线并排跑的时间。
单体仓库(Monorepo)是构建提速里最需要针对性优化的场景。Monorepo 把多个模块、多个服务放在同一个仓库,好处是原子化提交、统一依赖管理,但副作用是"牵一发动全身"——改了一个子模块,传统流水线却把所有模块全部重新构建和测试一遍,大量算力浪费在没变动的代码上。
按需构建(也叫受影响范围构建)是解决这个问题的关键:流水线先分析这次提交到底改了哪些模块,只构建和测试真正被影响的模块及其依赖,其余的跳过。
CNB 提供了 Monorepo 按需构建的实践方案,结合它的触发规则和分支 glob 匹配,可以做到"改了哪个模块,就只构建哪个模块"。再配合前文讲的缓存,未变动模块连编译都省了,构建时间自然从"整个仓库的规模"降到"改动模块的规模"。对于模块众多的前端、后端大仓,这一招往往能把十分钟的构建压到一两分钟。
缓存、并行、按需构建都做完,如果构建节点本身规格偏低,单任务还是会跑得慢。CNB 提供多种规格的构建节点,可按任务规模按需声明:
节点架构 | CPU 规格 | 适用场景 |
|---|---|---|
amd64 | 1~64 核 | 通用构建,可放大核数缩短编译时间 |
arm64 / v8 | 1~16 核 | ARM 架构的构建与验证 |
GPU | 固定 16 核 + 48GB 显存 | AI 训练、图形渲染等重算力任务 |
提速的实用搭配是:常规构建用中等规格节点 + 缓存,性价比最高;全量构建或大型编译任务临时放大核数,用并行度换时间;AI / 图形相关任务再用 GPU 节点。所有节点最大构建时长为 18 小时,常规构建完全够用。
需要提醒的是,规格越高单位时间消耗的资源也越多。社区版的计费按实际核时统计,云原生构建-CPU 免费额度为 160 核时/月,超额按 0.125 元/核时计费;云原生构建-GPU 无免费额度,按 0.5 元/核时计费。提速的同时留意用量,避免不必要的资源浪费。
a. 选离得近的构建镜像:每个 Job 在指定 Docker 镜像中运行,优先用官方预置的常用语言镜像,减少镜像拉取和初始化开销。
b. 让缓存键稳定:缓存能否命中,取决于依赖锁文件是否稳定。不要用会频繁变动的内容做缓存键,否则每次都是"未命中",缓存形同虚设。
c. 及时跳过没必要的阶段:比如只改了文档却触发全量测试,可以在触发规则里做路径过滤,让文档变更根本不拉起构建流水线。
d. 关注实际运行时长:构建完成后按实际运行时间统计用量,跨月执行的任务会计入结束时间所在的自然月,安排长任务时留意这一点。
构建提速没有一招通用的银弹,得先定位时间花在哪,再对症下药:依赖和产物用缓存复用,无依赖的任务并行跑,Monorepo 只构建改动的模块,再按任务规模选配合适的节点规格。这几招组合起来,通常能把"改一行等十分钟"压缩到可接受的范围。
腾讯云 CNB 的构建缓存、Pipeline/Stage/Job 并行结构、Monorepo 按需构建实践,以及 1~64 核 amd64、1~16 核 arm64、GPU 等多规格构建节点,正好覆盖了从缓存到算力的提速环节。如果你正被漫长的构建等待拖累,不妨从缓存和按需构建这两招开始试起。
想把这些提速手段落到自己的项目里,可以到腾讯云 CNB 给流水线加上 volumes 缓存、按 Monorepo 配按需构建,先跑通缓存命中,再按构建时长逐步调优节点规格。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。