• 自定义Gradle Task实现一键批量部署Springboot应用


        在未使用Jenkins自动化部署工具之前,我们部署使用gradle构建的单个springboot应用的流程大致如下:

    1、在idea使用gradle build命令编译打包jar包;

    2、打开jar包存放的windows目录窗口;

    3、打开访问服务端机器的SSH工具软件并前进到部署目录;

    4、上传第2步jar包到第3步目录

    5、停止当前应用进程;

    6、备份当前应用jar包;

    7、修改将要部署的jar包名称为当前环境指定的文件名;

    8、启动应用

    上面部署方式对于只有1、2个环境的应用来说还可以接受,不算太麻烦,但是对超过3个以上环境的部署会导致以下问题:

    1、步骤繁琐、多环境打包前要临时调整端口、数据库服务器配置,导致部署耗时较多;

    2、全部手工操作容易出错。

    为解决上面两个问题我研究了gradle的自定义task的相关配置知识,设计了一个一键部署到多个环境的task任务,此task的特点 如下:

    1、只需要通过点击一次idea gradle插件自定义的deploy命令即可实现编译、打jar包、批量部署到多个环境

    2、部署时会实时显示简单的部署日志,便于监控部署情况;

    3、模块化,方便添加新部署环境

    3、节约部署时间,一旦配置测试好就可以避免手动操作易出错的问题;

    假设我们要部署的应用叫“养护管理”(简称“养管”),它是一个包含spring application启动器的bimgis-mms-app模块+N个业务模块组成的应用,

    我们以此为例演示如何一键部署到服务端,养管有dev(开发)、test(测试)两个环境需要部署:

    step1 打开idea gradle插件面板

    step2 双击下图中的deploy命令(路径:bimgis-mms-app/Tasks/other/deploy)

    step3 查看部署日志,确认部署是否成功

    上面deploy命令内部运行流程如下:

    上图运行流程中涉及的8个步骤,依赖四类配置文件:

    (1)build.gradle:存放在本地PC项目目录,负责完成第1、2步骤;

    (2)restart.sh:存放在服务主机的部署目录,负责完成第3、4、5、6步骤;

      (3)   application.yml:springboot通用配置文件,负责完成第7步,设置加载哪个特定配置文件(profiles.active)、数据库连接池配置、mybatis配置等;

    (4)appliction-envName.yml:springboot特定环境配置文件,负责完成第8步,“envName“指环境名称,例如appliction-dev.yml,spring容器会先加载第(3)类文件然后根据其

    配置的profiles.active=dev,再加载appliction-dev.yml的配置,所以此文件用来保存不同环境的应用端口号、数据库服务器配置等差异化配置信息。

    以养管平台为例,进一步说明配置方法,养管有dev、test两个部署环境,这两个环境应用端口号、数据库配置如下:

    一、dev环境

    • 应用端口号:8383
    • 数据库IP/端口号:192.168.201.156:3306

    • 数据名称:bim_mms_0

    二、test环境

    • 应用端口号:8282
    • 数据库IP/端口号:192.168.201.155:3306

    • 数据名称:bimgis_mms_lexi

    我们将以上具有差异的配置信息分别存放到appliction-dev.yml、appliction-test.yml:

    接着在appliction.yml里的profiles.active属性配置默认加载appliction-dev.yml文件配置,即启用应用时会加载dev环境的配置:

    然后在build.gradle添加自定义任务deploy脚本:

    //##############部署Jar包到服务端脚本 start ###############
    //引用与服务端通信插件
    buildscript {
     repositories {
     jcenter()
     }
     dependencies {
     classpath 'org.hidetake:gradle-ssh-plugin:2.9.0'
     }
    }
    apply plugin: 'org.hidetake.ssh'
    
    //部署环境IP及登录账号
    remotes {
     webServerDev {
     host = '192.168.201.156'
     user = 'accountName'
     password = 'password'
     }
    
     webServerTest {
     host = '192.168.201.155'
     user = 'accountName'
     password = 'password'
     }
    }
    
    
    def HOST_LIST = ["dev","test"]//部署环境列表
    
    //部署文件存放位置及部署shell命令
    def SSH_RUN (String host) {
     ssh.settings {
     knownHosts = allowAnyHosts
       }
    
     ssh.run {
     if("dev" == host){
     session(remotes.webServerDev) {
     put from: "F:/IdeaProjects/bim/bimgis-web-application-mms/bimgis-mms-app/build/libs/bimgis-mms-app-1.0.0.jar", into: '/home/mmsuser/deploy/backend'
     execute """
     cd /home/mmsuser/deploy/backend
     sh restart.sh dev;
     """
     }
     }else if("test" == host){
     session(remotes.webServerTest) {
     put from: "F:/IdeaProjects/bim/bimgis-web-application-mms/bimgis-mms-app/build/libs/bimgis-mms-app-1.0.0.jar", into: '/home/mmsuser/mms'
     execute """
     cd /home/mmsuser/mms
     sh restart.sh test;
     """
     }
     }
     }
    }
    
    //部署任务执行入口
    task deploy {
    
     doLast {
     println("【############################开始部署############################】")
     int fileCount=0
     HOST_LIST.each {String host-> 
     fileCount++
             println("第${fileCount}个,hostName:${host}")
    
     println("部署到服务端")
     //部署到服务端
     SSH_RUN(host)
    
     println("部署成功!")
    
     }
     }
    }
    
    deploy.dependsOn(build)//编译和打jar包
    
    //##############部署Jar包到服务端脚本 end ###############
     

    test环境服务主机执行的restart.sh脚本代码如下:

    #! /bin/sh
    ORG_FILE='mms-app-1.0.0.jar' #原始文件
    DEPLOY_FILE='mms-app-1.0.0-8282.jar' #部署文件
    DEPLOY_LOG='mms-app-1.0.0-8282.log' #日志文件
    
    echo 'deploy task start...'
    
    #检查待部署的原始文件是否存在
    echo 'check orgFile is exist...' 
    if [ ! -f "$ORG_FILE" ];then
    echo "$ORG_FILE is not exist! deploy task fail!"
    exit 1
    fi
    
    #停止旧版本应用
    echo 'shutdown system...'
    PID=`ps x|grep $DEPLOY_FILE|grep -v grep |awk '{print $1}'`
    
    if [ -z "$PID" ]; then
    echo "system process is not exist,skip to next step"
    else
    kill -15 $PID
    sleep 5 #暂停5秒等待上一步system的进程退出
    fi
    
    #备份旧版本应用
    echo 'backup...'
    rm $DEPLOY_FILE'.bak'
    rm $DEPLOY_LOG
    mv $DEPLOY_FILE $DEPLOY_FILE'.bak'
    
    echo 'copy orgFile to deployFile'
    cp $ORG_FILE $DEPLOY_FILE
    
    #启动新版本应用
    echo 'boot system...'
    if [ $# -lt 1 ];then
    echo "no spring active arg,boot on default active profile" #未指定加载哪个appliction-envName.yml
    nohup java -jar $DEPLOY_FILE > $DEPLOY_LOG 2>&1 &
    else
    echo "boot on specified spring active profile: $1"#已指定加载appliction-envName.yml
    nohup java -jar $DEPLOY_FILE --spring.profiles.active=$1 > $DEPLOY_LOG 2>&1 &
    fi
    
    exit 0

    如果你要增加一个新部署环境add,需要做以下工作:

    1、增加appliction-add.yml文件;

    2、编辑build.gradle,增加如下红色代码:

    //部署环境IP及登录账号
    remotes {
    webServerAdd {
    host = '192.168.201.154'
    user = 'userName'
    password = 'password'
    }
    }


    def HOST_LIST = ["dev","test","add"]//部署环境列表

    ssh.run {
    if("add" == host){
    session(remotes.webServerAdd) {
    put from: "F:/IdeaProjects/bim/bimgis-web-application-mms/bimgis-mms-app/build/libs/bimgis-mms-app-1.0.0.jar", into: '/home/mmsuser/deploy/backend'
    execute """
    cd /home/mmsuser/deploy/backend
    sh restart.sh add;
    """
    }
    }else if("test" == host){
    session(remotes.webServerTest) {
    put from: "F:/IdeaProjects/bim/bimgis-web-application-mms/bimgis-mms-app/build/libs/bimgis-mms-app-1.0.0.jar", into: '/home/mmsuser/mms'
    execute """
    cd /home/mmsuser/mms
    sh restart.sh test;
    """
    }
    }
    }
    }

    3、增加对应的restart.sh文件

     

         至此对一键部署应用到多环境的介绍进入尾声,当前这种部署方式适合10人以下的开发团队在未使用部署流线工具之前过渡使用,ssh.run部分执行的shell脚本也可以替换为docker命令

    来支持部署到docker容器,此文仅作为优化项目开发流程的抛砖引玉,希望能对大家平时开发有所帮助,欢迎大家留言交流!

     

  • 相关阅读:
    ansj分词原理
    于erlang依赖的linux调优
    Gearman
    生成具有三态背景图片的按钮
    tracert
    Wings 3D
    jira
    Erlang编程语言的一些痛点
    QTreeView 限制特定的深度、特定深度下的列 是否可以编辑
    QStandardItemModel角色控制及QTreeView添加不同的右键菜单
  • 原文地址:https://www.cnblogs.com/wind1984/p/12359536.html
Copyright © 2020-2023  润新知