我正在构建一个Jenkins作业,它将一直运行我所有的分段测试,但不是一次全部(它们都依赖于共享硬件)。所以,我创建了并行作业,并使用信号量来确保只有有限的数量一次运行。 这里是我的管道再现问题的简化版本:Jenkins管道和信号灯
import java.util.concurrent.Semaphore
def run(job) {
return {
this.limiter.acquire();
try {
println "running ${job}"
build job
println "finished ${job}"
} finally {
this.limiter.release();
}
}
}
def getJobs() {
def allJobs = Jenkins.getInstance().getJobNames()
def stagingJobs = []
for(String job : allJobs) {
if (job.startsWith("staging/temp")) {
stagingJobs.add(job)
}
}
println "${stagingJobs.size()} jobs were found."
return stagingJobs
}
this.limiter = new Semaphore(2)
def jobs = [:]
for (job in getJobs()) {
jobs[job] = run(job)
}
parallel jobs
当我没有信号灯运行,一切正常。但上面的代码中,我得到不同的输出什么:
[Pipeline] echo
6 jobs were found.
[Pipeline] parallel
[Pipeline] [staging/temp1] { (Branch: staging/temp1)
[Pipeline] [staging/temp2] { (Branch: staging/temp2)
[Pipeline] [staging/temp3] { (Branch: staging/temp3)
[Pipeline] [staging/temp4] { (Branch: staging/temp4)
[Pipeline] [staging/temp5] { (Branch: staging/temp5)
[Pipeline] [staging/temp6] { (Branch: staging/temp6)
如果我查看管道的步骤,我可以看到前两个作业启动,它们的日志信息输出。但是,似乎跑步者从未收到关于登台作业完成的通知。结果,信号量从未释放,其他4个工作从未开始。这里有一个线程转储中期试验中,下游的建立有一定结束后:
Thread #7
at DSL.build(unsure what happened to downstream build)
at WorkflowScript.run(WorkflowScript:9)
at DSL.parallel(Native Method)
at WorkflowScript.run(WorkflowScript:38)
Thread #8
at DSL.build(unsure what happened to downstream build)
at WorkflowScript.run(WorkflowScript:9)
Thread #11
at WorkflowScript.run(WorkflowScript:6)
Thread #12
at WorkflowScript.run(WorkflowScript:6)
最终超时几个java.lang.InterruptedException
错误。
是否有可能在流水线中使用信号灯,还是有更好的方法来确保只有一部分工作同时运行?我宁愿避免为了简单的测试跑步者而转动节点。
的说明给他人:杰西·格里克指出这对詹金斯JIRA:“你可以不使用来自管道脚本本地Java并发原语 - 它运行在单线程虚拟机中“ – Crummy