一、这是一个demo

不单单用作并发构建docker镜像,因为使用sh'''  也是shell,也可作用其他类似用途

Jenkins并发还有另一个写法(详情看 在下面第四个)(不好扩展,新增并发步骤需要写上)

而单stage并发可让传入的参数个数去控制流程步骤,如传入S1-S18会有18个步骤,传入S1-S5就会生成5个

二、pipeline

def build_docker(service) {
    stages = {
        def thing = null
        waitUntil {
            // 获取一个资源
            thing = latch.pollFirst();
            return thing != null;
        }
        try {
            // 执行步骤 
            stage("构建${service}服务Docker镜像") {
                withEnv(["service=${service}"]){
                sh '''
                    echo "正在构建 ${service} 镜像"
                    sleep 15
                '''
                }
            }
        }
        finally {
            // 释放一个资源
            latch.offer(thing)
        }        
    }
    return stages
}

pipeline {
    agent {
        node {
            label "master"
        }
    }

    environment {
        // 规范:从Jenkins传入的变量,必须在这里填写后在引用
        build_com = "${build_com}"
    }
            
    parameters {
        // 参数化构建
        string defaultValue: 'S1 S2 S3 S4 S5 S6 S7 S8 S9 S10 S11 S12 S13 S14 S15 S16 S17 S18', description: '需要构建的服务', name: 'build_com', trim: true
    }
 
    options {
        // 添加控制台时间戳
        timestamps()
        // 超时时间/分
        timeout(30)
        // 不允许并发编译
        disableConcurrentBuilds()
    }

    stages {
        stage("开始") {
            steps {
                script {
                    sh '''
                         echo "start"
                    '''
                }
            }
        }
        
        stage("并发进行构建Docker镜像") {
            steps {
                script {
                    def stages = [:]
                    // 并行进程数量
                    MAX_CONCURRENT = 5
                    // 创建fifo
                    latch = new java.util.concurrent.LinkedBlockingDeque(MAX_CONCURRENT)
                     
                    // 往fifo中,填入最大个数元素
                    for(int i=0; i<MAX_CONCURRENT; i++)
                        latch.offer("$i")
                    
                    // 循环获取传入的值
                    for (service in build_com.tokenize(' ')){
                        stages[service] = build_docker(service)
                    }
                    // 并行步骤
                    parallel stages
                }
            }
        }
        
        stage("结束") {
            steps {
                script {
                    sh '''
                        echo "done"
                    '''
                }
            }
        }
        
    }
}

可控制node调度的写法

def build_docker(service, ARCH) {
    stages = {
        def thing = null
        waitUntil {
            // 获取一个资源
            thing = latch.pollFirst();
            return thing != null;
        }
        try {
            // ARCH变量是绑定node的label标签,当传入不同的label,去不同的机器上执行
            node("${ARCH}"){
                // 执行步骤 
                stage("构建${ARCH}架构${service}服务Docker镜像") {
                    withEnv([
                     "service=${service}",
                        "ARCH=${ARCH}"
                    ])
                    {
                        sh '''
                            echo "正在构建 ${service} 镜像"
                            sleep 15
                        '''
                    }
                }
            }
        }
        finally {
            // 释放一个资源
            latch.offer(thing)
        }        
    }
    return stages
}



pipeline {
    agent {
        node {
            label "master"
        }
    }
 
    environment {
        ARCH = "${ARCH}"
        build_com = "${build_com}"
    }

    parameters {
        // 参数化构建
        extendedChoice defaultValue: 'amd', description: 'CPU平台;默认amd', multiSelectDelimiter: ',', name: 'ARCH', quoteValue: false, saveJSONParameterToFile: false, type: 'PT_RADIO', value: 'amd,arm,mips64le', visibleItemCount: 3
        string defaultValue: 'S1 S2 S3 S4 S5 S6 S7 S8 S9 S10 S11 S12 S13 S14 S15 S16 S17 S18', description: '需要构建的服务', name: 'build_com', trim: true
    }
 
    options {
        // 添加控制台时间戳
        timestamps()
    }

    stages {
        stage("开始") {
            steps {
                script {
                    sh '''
                         echo "start"
                    '''
                }
            }
        }

        stage("并发进行构建Docker镜像") {
            steps {
                script {
                    def stages = [:]
                    // 并行进程数量
                    MAX_CONCURRENT = 6
                    // 创建fifo
                    latch = new java.util.concurrent.LinkedBlockingDeque(MAX_CONCURRENT)
                    
                    // 往fifo中,填入最大个数元素
                    for(int i=0; i<MAX_CONCURRENT; i++)
                        latch.offer("$i")
                    
                    // 循环获取传入的值
                    for (service in build_com.tokenize(' ')){
                        stages[service] = build_docker(service, "${ARCH}")
                    }
                    // 并行步骤
                    parallel stages
                }
            }
        }

        stage("结束") {
            steps {
                script {
                    sh '''
                        echo "done"
                    '''
                }
            }
            
        }
    }
}

注意项:不要勾选使用 Groovy 沙盒

不然会出错误

org.jenkinsci.plugins.scriptsecurity.sandbox.RejectedAccessException: Scripts not permitted to use new java.util.concurrent.LinkedBlockingDeque int

三、结果图

四、另一种Jenkins并发写法

pipeline {

    agent {
            node {
                label "master"
            }
    }

    stages {

        stage('开始') {
            steps {
                sh '''
                    echo "start"
                '''
            }
        }

        stage('并发步骤') {
            parallel {
                stage('步骤1') {
                    steps {
                        sh '''
                            echo "步骤1"
                        '''
                    }
                }

                stage('步骤2') {
                    steps {
                        sh '''
                            echo "步骤2"
                        '''
                        }
                    }

                }
            }
        }

        stage('结束') {
            steps {
                sh '''
                    echo "done"
                '''
            }
        }
                
    }
}

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐