Jenkins 分布式和并发构建

1. 分布式构建

2. 并发构建

 

 

1. 分布式构建

当持续集成系统管理了特别多的项目时,所有的任务都在主节点上同时执行,那么默认一个节点只能有 2 个 executor 执行任务,其他的就必须等待,这样会大大影响执行的效率,同时也不能满足在不同环境下的兼容性测试。

本节将介绍如何用 Jenkins 进行分布式构建任务。Jenkins 的分布式也是基于 master-slave 模式的,我们演示用的 master 节点在 windows 上,分别添加一个 linux 的从节点和 windows 的从节点。

  

1.1 添加 linux 节点

1)Jenkins-->Manage Jenkins-->Manage Nodes

2)新建节点

3)配置节点名称

Permanent Agent 表示的是常驻代理客户端。

4)节点详细配置

  • 名称:上一步创建的节点名称。
  • 并发构建数:指的是该节点最多有多少个执行器(executor),执行器是真正工作的单元,一个执行器就是一个单独的线程。
  • 远程工作目录:代理或者从节点上的工作目录,尽量使用绝对路径;目录不存在的话会自动创建,而且必须有写权限,否则会报错:hudson.util.IOException2: Failed to copy xxxx。
  • 标签:也叫 tag,用来区分或者标识某类节点,经常以工具链,操作系统等信息标识。
  • 用法:标识代理或者从节点的使用策略,有两种方式:
    1. Use this mode as much as possible:尽可能的使用此节点。
    2. Only build jobs with label expression matching this node:构建任务时指定的标签匹配本节点时才使用。
  • 启动方法:有 3 种方法启动:
    1. Launch agent agents via SSH:通过 SSH 通道连接节点(安装了 SSH Slaves plugin 插件才能看到)。
    2. Launch agent by connecting it to the master:通过 jnlp,javaweb 的方式连接。
    3. Launch agent via execution of command on the master:通过主节点的控制台连接子节点。
    • 我们选择的第 2 种方式,对应的配置如下:
      •   
      • 注意:如果定义了自定义工作目录,就不会使用代理的根目录,执行的日子信息会存到主节点中。而且该选项目前无法使用环境变量,因此建议使用绝对路径。
  • 可用性决定 Jenkins 的启动和停止:
    • 1)Keep this slave on-line as much as possible:尽可能保持节点在线【推荐】
      • 该模式下,Jenkins 会尽可能让代理保持在线。
      • 如果该代理由于临时性网络故障,Jenkins 会定期尝试重启它。
    • 2) Bring this agent online according to a schedule:让代理在特定的时间段内在线或者离线
      • 该模式下,Jenkins 会根据一个计划表来启动代理,并保持指定的时长。如果在计划周期内代理掉线,Jenkins 会定期尝试重启它。
      • 当代理在线时间达到字段计划启动的时间,它将会被下线。
      • 如果勾选了当有构建时保持在线,并且根据计划表应该下线,Jenkins 会等所有的构建任务完成后再下线。
    • 3)Bring this agent online when in demand,and take offline when idle:当代理被需要时保持在线,空闲时离线。
      • 该模式下,当代理被需要时 Jenkins 将会让代理上线,例如有排队的构建任务满足下列条件:
        • 在队列中排队时间达到需求延迟时间限制。  
        • 被构建任务指定(例如有一个匹配的标签表达式)。      
      • 如果发生下述情况,代理将会被下线:    
        • 代理没有需要构建的任务。     
        • 该代理已经空闲了指定的时间。        
  • 节点属性:根据需要配置即可:
    1. Disable deferred wipeout on this node:在当前节点上,是否开启延迟清理;
    2. Environment variables:配置环境变量,可以在脚本中引用;
    3. Tool Locations:工具的目录【推荐】。可以替换系统设置的各种工具目录。如:JDK 目录、Ant 目录、Maven 目录等。好处就是在不更改 Job 配置的情况下,不同环境(如 Windows 和 Linux)的 Job 配置通用。

5)配置完成后节点状态

Jenkins 提供了两种方式让 agent 和 master 进行连接,我们选择第 2 种,因为命令行的形式更方便自动化。

6. 下载 agent.jar

文件可通过此网址 http://127.0.0.1:8080/jenkins/jnlpJars/agent.jar 或者单击以下超链接:

7. 将 agent.jar 文件上传到 linux 节点中

进入到代理节点的工作目录 jenkins 下,执行 rz 命令上传文件。注意:远程的代理节点中一定已经安装好了 jdk。

8. 获取 windows 主节点的 IP 地址

9. linux 节点执行以下命令启动节点

java -jar agent.jar -jnlpUrl http://192.168.1.10:8080/jenkins/computer/centos7/slave-agent.jnlp -secret 6b317df862212450891bb851e8f673d2d18e0c0b15bc46117bebe51c176d56b5 -workDir "/jenkins"

注意:以上 IP 为主节点的 IP 地址。

10. 执行 pineline 脚本

pipeline {
    agent {
        label 'linux'
    } 

    stages {
        stage('Hello') {
            steps {
                echo 'Hello World'
            }
        }
    }
}    

建日志:

切换到 linux 节点中 Jenkins 的工作目录,可以看到配置节点时指定的 remoting 目录,下面有节点的执行日志:

  

1.2 添加 windows 节点

和上述添加 linux 节点的步骤大同小异,此处不再赘述。

一般 Jenkins 都是部署到 linux 系统,因为 windows 系统相当不稳定。

 

2. 并发构建

2.1 原理

并行构建指的是某个 stage 或者 step 同时执行,比如说我们的 UI 测试脚本要在 Chrome、IE 和 Firefox 3 种浏览器下同时执行,或者是 APP 需要在不同型号的手机上执行,或者执行不同分支的代码等等,以上场景如果是顺序执行的话,显然效率是很低的,而且这些场景也都是相对独立的,并无依赖关系,那么我们能不能实现并行执行呢?在 pipeline 中并行构建需要用到 parallel 指令。

parallel{} 里面包含多个 stage{…},只有最后一个 stage{…} 内部支持嵌套多个 stages{…}。在 parallel{…} 中如果要设置只要里面有一个 stage{…} 运行失败就强制停止,可以使用表达式 failFast true 来进行控制。

pipeline 脚本如下:

pipeline {
    agent any
    stages {
        stage('Non-Parallel Stage') {
            steps {
                echo 'This stage will be executed first.'
            }
        } 
        stage('Parallel Stage') {
            failFast true
            parallel {
                stage('并行一') {
                    steps {
                        echo "并行一"
                    }
                } stage('并行二') {
                    steps {
                        echo "并行二"
                    }
                } stage('并行三') {
                    stages {
                        stage('Nested 1') {
                            steps {
                                echo "In stage Nested 1 within Branch C"
                            }
                        } 
                        stage('Nested 2') {
                            steps {
                                echo "In stage Nested 2 within Branch C"
                            }    
                        }
                    }
                }
            }
        }
    }
}

成功执行结果

并行 1、并行 2 和并行 3 三个 stage 之间的关系是并行的,下图显示都执行成功:

失败执行结果

将并行 2 中 echo 改为 printf 指令,查看 pipeline 执行结果,如下:

如果有需要一个不通过,无须执行后面 pipeline 脚本的场景,可以使用 failFast true 语句。

如上图所示,原本并行一、并行二和并行三下面两个嵌套的 stage 都在同一时间并发执行,由于设置了 failFast true,在并行二这个 stage 发生了报错后,导致并行三下面两个前提的 stage 都显示 aborted 了,从控制台日志也可以看出来。

 

2.2 示例:分别用 chrome/IE/Firefox 并行测试

@Library('share-lib') _
pipeline{
    agent any
    options {
        buildDiscarder(logRotator(numToKeepStr:'3'))
    } 
    environment {
        config_file = "\\Config\\ProjVar.py"
    } 
    stages{
        //从 github 拉取测试脚本
        stage("checkout test script") {
            steps{
                script {
                    checkout([$class: 'GitSCM',
                    branches: [[name: '*/master']],
                    doGenerateSubmoduleConfigurations: false,
                    extensions: [[$class: 'CloneOption', noTags: false, reference: '',
                    shallow: true, timeout: 20]],
                    submoduleCfg: [],
                    userRemoteConfigs: [[credentialsId: 'gtihub', url: 'https://github.com/kongsh8778/keywordFramework']]])
                }
            }
        } 
        //执行测试
        stage("Parallel Selenium Test"){
            failFast true
            parallel {
            //firefox 浏览器
            stage("firefox"){
                steps{
                    script{
                        //修改配置文件中浏览器类型
                        try{
                            setkey.setKeyValueByWriteFile("browser", "firefox", config_file)
                            file_content = readFile config_file
                            //println file_content
                        }catch (Exception e) {
                            error("Error met:" + e)
                        } 
                        //执行测试
                        bat("py -3 main.py")
                    }
                }
            } 
            //chrome 浏览器
            stage("chrome"){
                steps{
                    script{
                        //修改配置文件中浏览器类型
                        try{
                            setkey.setKeyValueByWriteFile("browser", "chrome", config_file)
                            file_content = readFile config_file
                            //println file_content
                        }catch (Exception e) {
                            error("Error met:" + e)
                        } 
                        //执行测试
                            bat("py -3 main.py")
                        }
                    }
                }
            }
        }
    } 
    post{
        always {
            echo 'This will always run'
            //workspace 下的临时目录
            deleteDir()
    } 
        success {
            echo 'This task is successful!'
            //记录日志信息
            script {
                emailext attachLog: true, body: text, compressLog: true, mimeType: 'text/html', subject: '$PROJECT_NAME - Build # $BUILD_NUMBER - $BUILD_STATUS!',  to: '455576105@qq.com'
            }
        }
    }
}

 

posted @ 2021-04-21 15:14  Juno3550  阅读(2473)  评论(0编辑  收藏  举报