1. 引言
在 Jenkins 中,我们需要合理控制流水线任务的执行方式,以确保资源被正确使用,并避免任务之间的冲突。
一个常见的需求是:防止相同类型的两个流水线任务在同一个节点上同时运行。当多个任务并发运行在同一个节点上时,可能会导致 CPU、内存或磁盘 I/O 资源竞争,也可能因为共享工作区而造成文件冲突甚至执行结果不一致。
本文将介绍几种在 Jenkins 中控制任务并发执行的方法,帮助你构建更稳定、高效的持续集成流水线。
2. 为什么需要限制并行执行
在同一个节点上运行多个相同类型的任务,可能会带来以下几个问题:
✅ 资源竞争:两个任务同时占用大量 CPU 或内存时,可能会互相拖慢甚至失败。例如,一个任务执行编译,另一个任务执行测试,它们同时运行可能导致资源耗尽。
✅ 工作区冲突:Jenkins 默认使用同一个工作目录。如果多个任务并发执行,文件可能被覆盖或损坏,导致构建过程不稳定,难以排查错误。
✅ 共享资源污染:如果任务修改了共享资源(如配置文件或数据库),一个任务可能会干扰另一个任务,造成数据错误或测试失败。
因此,我们的目标是:保证同一节点上,同一类型任务只能有一个实例在运行,同时允许不同节点上并发执行,以提升整体效率。
3. 使用 disableConcurrentBuilds
方法
Jenkins 提供了一个内置选项:disableConcurrentBuilds
,用于禁止同一个任务的并发执行。它保证当前任务执行完成前,不会启动新的实例。
这个方法适用于全局限制,无论任务运行在哪个节点上,都只能串行执行。
示例代码:
pipeline {
agent any
options {
disableConcurrentBuilds()
}
stages {
stage('Build') {
steps {
// 编译步骤
}
}
stage('Test') {
steps {
// 测试步骤
}
}
}
}
⚠️ 注意:该方法限制的是整个任务级别的并发,不是按节点划分的。如果你有多个节点,也只能同时运行一个任务实例,这在某些场景下可能过于严格。
4. 使用 Throttle Concurrent Builds 插件进行精细化控制
如果你希望允许不同节点上的并发执行,但禁止同一节点上的并行任务,推荐使用 Throttle Concurrent Builds Plugin。
4.1 安装插件
安装步骤如下:
- 进入 Jenkins 管理界面(Manage Jenkins)
- 打开插件管理(Manage Plugins)
- 在“可用”标签页中搜索
Throttle Concurrent Builds
- 勾选后安装,无需重启
4.2 配置限制类别(Category)
- 进入 Manage Jenkins > Configure System
- 找到 Throttle Concurrent Builds 配置区域
- 添加一个新的类别(Category),例如命名为
myThrottleCategory
- 设置 Maximum Concurrent Builds Per Node 为
1
- 可选设置 Maximum Total Concurrent Builds 控制全局并发数
配置完成后,界面如下图所示:
4.3 在 Jenkinsfile 中使用
pipeline {
agent any
options {
throttleJobProperty(
categories: ['myThrottleCategory'],
throttleEnabled: true,
throttleOption: 'category'
)
}
stages {
stage('Build') {
steps {
// 编译步骤
}
}
stage('Test') {
steps {
// 测试步骤
}
}
}
}
通过这种方式,你可以实现:同一节点上只允许一个属于该类别的任务运行,但不同节点可以并发执行。
5. 使用 Lockable Resources 插件进行节点级资源锁定
另一种方法是使用 Lockable Resources Plugin,它允许你对特定资源(如节点)进行锁定,从而控制任务的并发执行。
5.1 安装插件
安装步骤与上述插件类似:
- 进入 Manage Jenkins > Manage Plugins
- 搜索
Lockable Resources Plugin
并安装
5.2 配置可锁定资源
- 进入 Manage Jenkins > Configure System
- 找到 Lockable Resources 配置区域
- 添加一个可锁定资源,例如命名为
MyJobResource
- 可选设置标签或描述,便于识别
5.3 在 Jenkinsfile 中使用锁
pipeline {
agent any
stages {
stage('Preparation') {
steps {
lock(resource: 'MyJobResource') {
echo '锁已获取,执行关键步骤'
// 放置需要互斥执行的步骤
}
}
}
stage('Other Steps') {
steps {
echo '执行非关键步骤'
// 这些步骤可以并发执行
}
}
}
}
✅ 优势:这种方式只对关键步骤加锁,不影响其他部分的并发执行。
⚠️ 缺点:需要手动管理资源定义,适合对并发控制有更高灵活性需求的场景。
6. 最佳实践建议
选择并发控制方法时,建议根据你的 Jenkins 环境和任务特性来决定:
方法 | 适用场景 | 优点 | 缺点 |
---|---|---|---|
disableConcurrentBuilds |
简单任务、小规模环境 | 简洁易用 | 控制粒度粗,影响整体并发 |
Throttle Concurrent Builds | 多节点部署、需节点级并发控制 | 支持按节点并发 | 需要配置插件和类别 |
Lockable Resources | 仅关键步骤需互斥 | 控制粒度细 | 需手动定义资源 |
📌 建议:
- 如果你的节点资源充足,但担心同一节点任务冲突,优先使用 Throttle 插件。
- 如果任务中只有部分逻辑需要互斥,使用 Lockable Resources 插件更合适。
- 如果你希望快速实现串行执行,
disableConcurrentBuilds
是最直接的选择。
7. 小结
本文介绍了三种防止相同类型 Jenkins 流水线任务在同一个节点上并行运行的方法:
- ✅ 使用
disableConcurrentBuilds
:适用于全局限制,简单有效 - ✅ 使用 Throttle Concurrent Builds 插件:支持按节点限制,适合多节点环境
- ✅ 使用 Lockable Resources 插件:实现关键步骤锁定,控制粒度更细
合理使用这些方法,可以有效避免资源竞争、工作区冲突等问题,提升 Jenkins 流水线的稳定性与执行效率。