V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Coding.NET 轻量级社交
开源项目广场
使用帮助
意见反馈
CodingNET
V2EX  ›  Coding

持续集成之 Spring Boot 实战篇

  •  
  •   CodingNET · 2019-03-08 15:43:24 +08:00 · 3748 次点击
    这是一个创建于 2087 天前的主题,其中的信息可能已经有所发展或是发生改变。

    本文作者:CODING 用户 - 何健

    这次实战篇,我们借助「 CODING 持续集成」,实现一个简单的 Spring Boot 项目从编码到最后部署的完整过程。本教程还有 B 站视频版,帮助读者更好地学习理解。


    思路

    在线上环境构建、测试、部署

    这种情况,通常会将 jenkins 安装在服务器上,确保构建测试等操作环境和线上环境一致。

    此时通常会在 jenkins 中配置好需要持续集成的仓库,以及具体流程。

    这种方式非常简单粗暴,也非常有效,但是缺点也很明显。可能 jenkins 会成为线上环境的旁站漏洞,这是非常不安全的。

    那么,我们就需要更高级的方式,可以线上环境之外的构建测试,最终部署到线上环境。「 CODING 持续集成」正是提供这类持续集成模式的平台。

    不在实际部署服务器上构建、测试

    为了避免占用线上服务器的资源,也为了避免安全问题,我们可以使用单独的 jenkins (或者其它此类软件)完成构建、测试、分发,实际部署通过单独的 webhook 实现。这样就可以避免在线上环境安装 Jenkins,还可以避免更复杂的系统安全维护。

    这样做的优点:不会影响在线服务; 缺点:部署地机器最好是可以公网访问的,否则会无法完成后续分发步骤。

    终极解决方案:使用 SaaS 化的 Jenkins

    Software as a Service,软件即服务。「 CODING 持续集成」集成了 SaaS 化的 Jenkins 等主流企业开发流程工具,实现了 DevOps 流程全自动化。开箱即用,直接用它就好!

    捋一下思路

    我们这次实战针对后一种思路

    1. 检出代码

    2. 构建

    3. 测试

    4. 分发

    5. 触发部署


    实战

    实际体验,还是很不错的。

    视频地址:CODING 持续集成 - Spring Boot 项目

    第一步:初始化一个持续集成

    1、首先,我们需要进入准备持续集成的项目。

    这里我用 start.spring.io 初始化一个 demo 示例项目,并推送到仓库。

    为了方便大家,亲自体验,我准备了一个现成的仓库,可以直接 git clone 下来再 git push 到自己账户下使用。仓库地址:demoForCI

    2、解压 demo 项目,进入 demo 目录,初始化仓库。

          cd g:\demo\
          git init
          git set remote giturl
          git add ./
          git commit -m 'init repo'
          git push -u origin master
    

    别忘了 git config user.name yournamegit config user.email youremail

    3、开始体验

    仓库准备好后,就可以开始体验「 CODING 持续集成」

    第一次的使用,需要先创建一个 Jenkinsfile,很多小伙伴会说,第一次用,不知道是啥。

    没关系,「 CODING 持续集成」已经给我们准备好了模板,非常容易理解,可以认为是特定格式语法写一套 task 流程。

    点击一下 “简易模板”,更具实际情况修改一下就可以。

    第二步:编写 Jenkinsfile

    为了方便理解,我们从简易模板开始,分别修改对应阶段的任务。

    1、配置构建环境,「 CODING 持续集成」目前支持 java-8、python-3.5、ruby-2.3、go-1.11 等等。

    在 Jenkinsfile 的 pipeline 里添加:

        agent {
          // 此处设定构建环境,目前可选有
          // default, java-8, python-3.5, ruby-2.3, go-1.11 等
          // 详情请阅 https://dev.tencent.com/help/knowledge-base/how-to-use-ci#agents
          label "java-8"
        }
    

    2、检出

    这里不得不说,「 CODING 持续集成」这里做的还是很方便的,提供了适用于好几种不同场景的模板。默认简易模板是带有检出部分的,我们可以根据实际情况进行修改。默认情况下,env.GIT_BUILD_REF 的值就是 master 主分支,实际上我们可以定制为其它专门用于构建发的分支。

    这里,大家可以自己修改具体要检出的分支。

        stage("检出") {
          steps {
              sh 'ci-init'
              checkout(
                [$class: 'GitSCM', branches: [[name: env.GIT_BUILD_REF]], 
                userRemoteConfigs: [[url: env.GIT_REPO_URL]]]
              )
          }
        }
    

    3、构建

        stage("构建") {
          steps {
            echo "构建中..."
            sh 'java -version'
            sh 'mvn package'
            echo "构建完成."
            archiveArtifacts artifacts: '**/target/*.jar', fingerprint: true // 收集构建产物
          }
        }
    

    这里需要注意,Spring Boot 的 pom 中需要添加一个插件。 修改后:

        <plugins>
          <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
          </plugin>
          <!-- 下面是添加的插件 -->
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>2.6</version>
            <configuration>
            <skipTests>true</skipTests>
            </configuration>
          </plugin>
    

    4、测试

    这里我偷个懒,只做了单元测试,

    没有提取测试报告,大家可以根据实际项目定制这个流程。

        stage("测试") {
          steps {
              echo "单元测试中..."
              sh 'mvn test'
              echo "单元测试完成."
              //junit 'target/surefire-reports/*.xml' // 收集单元测试报告的调用过程
          }
        }
    

    5、分发 jar 包到目标服务器

    这里比较无奈,我没有单独针对这次演示写部署 jar 包和上传 jar 包的 webhookApi,但是构建好的 jar 包需要要放置到待部署的服务器。

    于是有了这个过程,借助 scp私钥来上传构建好的 jar 包。

    这里千万记着提前部署好密钥。并且将密钥放到仓库一份,用于分发 jar 包。

        stage("分发 jar 包") {
          steps {
            echo "分发中..."
            echo "chmod 600 pkey"
            sh 'chmod 600 authorized_keys.pem'
            echo "upload"
            sh 'scp -i authorized_keys.pem ./target/*.jar root@yourip:/root/'
            echo "准备部署"
          }
        }
    

    6、部署

    前面有提到,这里部署仍然需要触发一个钩子,否则只能手动部署了。

    这里我写了一个最简单的,实际上我们可以写细致一点,判断一下接口返回的结果再根据结果输出部署情况。

        stage("部署") {
          steps {
            sh 'curl http://youapi'
            echo "部署完毕"
          }
        }
    

    第三步:保存 Jenkinsfile 并运行

    修改好 Jenkinsfile 和 pom.xml 。

    我们要保存 Jenkinsfile,编辑框可以直接编辑内容,编辑好可以直接提交到仓库下的 ./Jenkinsfile

    接下来, 平台会自动读取 Jenkinsfile 并开始走持续集成的流程:

    持续集成的流程是可以看到的:

    每个阶段都对应 Jenkinsfile 一个 stage, 我们可以点击查看对应阶段的构建结果。

    第四步:排查持续集成的报错

    如果某个过程出错,「 CODING 持续集成」的流程会停止,并提示失败。此时我们可以进入具体节点查看具体失败原因。

    比如现在是提示“分发 jar 包失败”,那么我们可以点击对应节点展开看看日志,排查具体分发失败的原因。

    现在可以清晰地看到,报错原因是我没有填写正确的主机 ip。


    文中涉及的文件及代码

    Jenkinsfile

    pipeline {
        agent {
            // 此处设定构建环境,目前可选有
            // default, java-8, python-3.5, ruby-2.3, go-1.11 等
            // 详情请阅 https://dev.tencent.com/help/knowledge-base/how-to-use-ci#agents
            label "java-8"
        }
        stages  {
            // 检出仓库
            stage("检出") {
                steps {
                    // 这里 sh 调用 ci-init 初始化
                    sh 'ci-init'
                    // 这里检出仓库,默认检出分支为环境变量中的 GIT_BUILD_REF
                    checkout(
                      [$class: 'GitSCM', branches: [[name: env.GIT_BUILD_REF]], 
                      userRemoteConfigs: [[url: env.GIT_REPO_URL]]]
                    )
                }
            }
            // 构建 jar 包
            stage("构建") {
                steps {
                    echo "构建中..."
                    // 输出 java 版本
                    sh 'java -version'
                    // 调用 maven 构建 jar 包
                    sh 'mvn package'
                    echo "构建完成."
                    //收集构建产物,这一步成功,我们就可以在平台上看到构建产物
                    archiveArtifacts artifacts: '**/target/*.jar', fingerprint: true // 收集构建产物
                }
            }
            // 测试
            stage("测试") {
                steps {
                    echo "单元测试中..."
                    // 做单元测试
                    sh 'mvn test'
                    echo "单元测试完成."
                }
            }
            // 分发 jar 包,这里只是简单的通过 scp 分发 jar 包到目标机器指定目录
            stage("分发 jar 包") {
                steps {
                    echo "分发中..."
                    echo "chmod 600 pkey"
                    sh 'chmod 600 authorized_keys.pem'
                    echo "upload"
                  	sh 'scp -i authorized_keys.pem ./target/*.jar root@youip:/root/'
                    echo "准备部署"
                }
            }
            // 部署 jar 包
            stage("部署") {
                // 这里需要触发一个部署的 webhook,可以是一个很简单的重启 java 进程的操作
                steps {
                    // 用 curl 来触发 hook
                    sh 'curl http://baidu.com'
                    echo "请登录服务器手动部署"
                }
            }
        }
    }
    

    pom.xml

    文中所用 Spring Boot 示例项目的 pom.xml

    实际上,大家可以直接去 start.spring.io 参考照这份 pom 来创建一个 demo。

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    	<modelVersion>4.0.0</modelVersion>
    	<parent>
    		<groupId>org.springframework.boot</groupId>
    		<artifactId>spring-boot-starter-parent</artifactId>
    		<version>2.1.2.RELEASE</version>
    		<relativePath/> <!-- lookup parent from repository -->
    	</parent>
    	<groupId>tech.hejian</groupId>
    	<artifactId>codingj8</artifactId>
    	<version>0.0.1-SNAPSHOT</version>
    	<name>codingj8</name>
    	<description>coding project for Spring Boot</description>
    
    	<properties>
    		<java.version>1.8</java.version>
    	</properties>
    
    	<dependencies>
    		<dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-starter-web</artifactId>
    		</dependency>
    
    		<dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-devtools</artifactId>
    			<scope>runtime</scope>
    		</dependency>
    		<dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-starter-test</artifactId>
    			<scope>test</scope>
    		</dependency>
    	</dependencies>
    
    	<build>
    		<plugins>
    			<plugin>
    				<groupId>org.springframework.boot</groupId>
    				<artifactId>spring-boot-maven-plugin</artifactId>
    			</plugin>
    			<plugin>
    				<groupId>org.apache.maven.plugins</groupId>
    				<artifactId>maven-surefire-plugin</artifactId>
    				<version>2.6</version>
    				<configuration>
    				<skipTests>true</skipTests>
    				</configuration>
    			</plugin>
    		</plugins>
    
    
    	</build>
    
    </project>
    

    总结

    CODING 是一个面向开发者的云端开发平台,提供 Git/SVN 代码托管、任务管理、在线 WebIDE、Cloud Studio、开发协作、文件管理、Wiki 管理、提供个人服务及企业服务,其中「 CODING 持续集成」集成了 SaaS 化的 Jenkins 等主流企业开发流程工具,实现了 DevOps 流程全自动化,为企业提供软件研发全流程管理工具,打通了从团队构建、产品策划、开发测试到部署上线的全过程。

    目前尚无回复
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1883 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 16:21 · PVG 00:21 · LAX 08:21 · JFK 11:21
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.