Java代码自动部署

Java代码自动部署

【 ①Java代码自动部署-总结简介】

       代码部署是每个软件开发项目组都会有的一个流程,也是从开发环节到发布功能必不可少的环节。对于Java开发者来讲,Java代码的发布部署也是常常须要作的一件事,特别是互联网公司。代码的发布上线关系到保证生产环境可以正常启动及功能是否能正常运行,因此代码部署在整个项目开发周期仍是占据很重要的地位。html

       因为本人近期在学习Java代码自动发布相关的知识,此系列文章是对这次学习到的知识进行巩固和总结;同时,也但愿可以帮助到和我同样对此方面知识感兴趣的同行们。言很少说,直接进入真题。下面针对这次系列文章作一个简要的概述。java

一、学习代码自动部署的目的

       高效且简化代码的部署发布git

二、使用的相关工具及技术

       一、 CentOS操做系统(可使用虚拟机安装Linux系统)web

       二、 Mavenshell

       三、 Gitapache

       四、 Shell脚本数组

       五、 Jenkinstomcat

三、学习代码自动发布相关技术的顺序

    阶段1:bash

    优势:部署流程简单方面,开发完成后开发人员在开发环境便可进行代码部署上线。服务器

    缺点:发布流程粗糙,代码部署不够严谨,不建议生产环境使用此方式。

    阶段2:

    优势:由Git进行项目版本管理,下降了代码发布的风险,发布过程有运维人员进行发布。

    缺点:因为代码的发布由运维人员发布,需开发人员配合进行代码发布部署,与发布部署不成功,得由开发人员查找问题,增长了部署复杂性。

    阶段3:

    优势:由Jenkins工具进行代码的发布部署,规范了代码的发布流程,提供可视工具监听整个发布流程等。

    缺点:对技术要求更高了,须要了解Jenkins工具,会编写Shell脚本等。

四、Java代码自动部署总结分为如下系列

        ①总结简介

        ②使用Maven进行代码部署

        ③使用Shell进行代码部署

        ④使用Jenkins进行代码部署

        ⑤课程总结及心得

【 ②使用Maven进行代码部署】

       在使用maven进行代码发布的时候,须要用Maven工具的相关插件将须要部署的项目发布到指定的服务器的部署目录中。

在学习此技术时,我用的的是一个秒杀项目的ssm版,你们在学学习此技术的时候能够用简单一点的Maven项目进行测试。因本项目是学习如何进行部署项目技术的,本次就针对具体项目进行介绍。

一、 使用Maven进行部署项目要求

    1) 项目自己属于Maven项目(必要条件)

    2) 须要部署的是war包

    3) 引入插件

    在须要部署的项目的pom,xml文件中引入tomcat插件,在project->build-> plugins节点引入tomcat插件。

<build>

   <plugins>

      <plugin>

         <groupId>org.apache.tomcat.maven</groupId>

         <!-- 引入tomcat插件 -->

         <artifactId>tomcat7-maven-plugin</artifactId>

         <configuration>

            <!-- <url>http://localhost:8080/manager</url> -->         <!-- tomcat6部署管理路径 -->

            <url>http://192.168.25.133:8080/manager/text</url>        <!-- tomcat7部署管理路径 -->

            <!-- tomcat控制台帐号 -->

            <username>admin</username>                                <!-- tomcat的管理员帐号 -->

            <!-- tomcat控制台密码-->

            <password>admin</password>

            <!-- 本地运行时指定的端口号  -->

            <port>8080</port>

            <path>/seckill-manager</path>                            <!-- 部署路径 -->

            <charset>UTF-8</charset>

            <encoding>UTF-8</encoding>

         </configuration>

      </plugin>

   </plugins>

</build>

   4) 执行Maven的redeploy操做

   执行的命令:tomcat7:redeploy

   在eclipse下配置的命令以下:

二、须要注意的问题点

  一、在将项目发布到远程Tomcat时须要启动远程Tomcat管理控制台帐号

  开启tomcat管理控制台帐号地址为:Tomcat安装目录/conf/tomcat-users.xml文件

  在tomcat-users.xml文件中须要配置容许访问纯文本接口权限,以便maven的tomat插件可以经过此方式进行部署项目。

  在tomcat-users节点新增role属性和user属性,以下:

<role rolename="manager-script" />

<role rolename="manager-gui"/>

<user username="admin" password="admin" roles="manager-gui,manager-script"/>

  解释:给帐号admin配置manager-script及manager-gui权限

  Tomcat角色解释图:

  二、在须要远程发布到的目标Tomcat应该是运行状态,保证Maven的tomcat插件可以访问到目标Tomcat完成项目的部署。

 

【③使用Shell进行代码部署】

  在使用Shell脚本进行从新部署项目时,须要掌握Shell脚本的编写,Shell脚本须要完成如下功能:

  一、 将代码clone到服务器指定目录

  二、 根据pom.xml文件将代码打包成war包

  三、 将war发布到指定服务器

   

  环境要求:

  一、 安装Maven并配置环境变量

  二、 Git客户端,并配置环境变量

  三、 熟悉Shell脚本相关知识

  一、编写Shell脚本

  在Linux的指定目录新建shell脚本,我是在项目的专用tomcat根目录新建了shell脚本,方便进行tomcat集群部署操做。脚本内容以下:

#!/bin/bash

#shell功能概要:seckill的service提供者构建shell

#发布service提供者的服务器的进程名

serverName="seckill_provider"

#获取发布service提供者的服务器的进程PID

PID=$(ps -ef | grep $serverName | grep -v grep | awk '{ print $2 }')

#java代码本地仓库地址

javaBaseSrc="/opt/java_project_src/"

#项目路径

javaProjectSrc="sekill/seckill-manager/seckill-service/target/seckill-service.war"

#发布的tomcat集群,数组方式存储

projectServicersPath=(/opt/seckill-tomcat/seckill-tomcat-02 /opt/seckill-tomcat/seckill-tomcat-03)

projectName="sekill"

#循环强制中止指定tomcat

for var in ${PID};

do

  echo "准备强制中止PID:$var"

  kill -9 $var

done

echo "kill $serverName sucess"

#切换到git本地仓库目录

cd $javaBaseSrc

#删除仓库库中代码

rm -rf $projectName

echo "从/opt/java_project_src仓库中删除项目$projectName成功"

#从远程仓库下载代码,因涉及到帐户信息,此处更改成描述信息

git clone 远程git仓库项目URL

cd $javaBaseSrc/sekill/seckill-manager

#安装项目并跳过测试

mvn -Dmaven.test.skip=true clean install

#判断执行上面mvn操做的返回值是否为0

if [ $? -ne 0 ]

then

  echo "构建失败,请查看代码问题!"

  exit 1;

fi

#循环将项目部署到集群tomcat中

for projectServicer in ${projectServicersPath[@]}

do

       cp $javaBaseSrc$javaProjectSrc $projectServicer/webapps

       echo "$projectServicer 代码发布成功!"

       sh $projectServicer/bin/startup.sh

       if [ $? -ne 0 ]

       then

         echo "$projectServicer 启动失败"

         exit 1;

       else

         echo "$projectServicer 启动成功";

       fi

done

echo "启动 $serverName 成功"

  二、须要注意的问题点

  在编写Shell脚本时须要知道每句Shell的含义,尽量将全部问题点都能考虑到,好比:

  a) 强杀进程问题

  进行PID=$(ps -ef | grep $serverName | grep -v grep | awk '{ print $2 }')时,要肯定查询的只是目标Tomcat的进程pid,防止在后续强制中止时将其余应用Tomcat误强行中止,这里建  议给每个目标Tomcat设置指定的进程名,设置方法为:

  在指定tomcat的bin/ setclasspath.sh文件中找到if [ -z "$_RUNJAVA" ]判断语句,进行如下设置便可

if [ -z "$_RUNJAVA" ]; then

#_RUNJAVA="$JRE_HOME"/bin/java
    #注释tomcat默认进程名,设置指定的进程名称,集群的时候能够进行编号01,02,03设置

cp "$JAVA_HOME/bin/java" "$JAVA_HOME/bin/seckill_consumer01"

 _RUNJAVA="$JRE_HOME/bin/seckill_consumer01"

fi

  b) Shell脚本尽量通用

  我吸收了如今比较流行的一句话“约定大于配置”及平时所看所想,在编写Shell脚本时能够提取可变或多处使用的变量,使整个Shell脚本尽量提炼成通用,以便相似项目部署可使用现有脚本进行更改后使用,减小从新编写新Shell脚本带来不可控的问题。

【④使用Jenkins进行代码部署】

  在使用Jenkins进行项目部署时,须要将Jenkins的war包放在服务器的指定位置。Jenkins的war的下载能够去Jenkins的官网进行下载。

  使用Jenkins进行代码部署时须要的环境支持:

  一、安装Maven并配置环境变量

  二、Git客户端,并配置环境变量

  三、熟悉Shell脚本相关知识

  四、对Jenkins有必定了解

 

  使用Jenkins进行代码部署以下:

  一、 启动Jenkins工具

  在jenkins.war目录执行如下命令操做启动Jenkins工具。

  [xiongshx@localhost jenkins]$ java -jar jenkins.war

    Jenkins工具初始化的一些操做能够百度或者去Jenkins查看能够参考【https://www.cnblogs.com/cheng95/p/6542036.html】

  初始化后须要进行的配置

  工具配置

  【系统管理】->【全局工具配置】

   Jdk配置:

 

   Git配置:

   Maven配置:

 

  二、 新建任务

 

  须要注意的点:

  一、填写源码仓库地址

 

    二、构建时操做及自定义shell代码

 

Shell代码以下:

#!/bin/bash

#shell功能概要:seckill的Web消费者构建shell

#引用的技术有:git、maven

#发布web消费者的服务器的进程名

serverName="seckill_consumer"

#获取发布web消费者的服务器的进程PID

PID=$(ps -ef | grep $serverName | grep -v grep | awk '{ print $2 }')

#须要在脚本开始时添加export BUILD_ID=dontKillMe。

#缘由:由于Jenkins执行完当前任务以后须要执行下一个任务,此时Jenkins会直接把tomcat进程杀掉,

#所以在脚本中编写的tomcat启动命令是不会执行的。

export BUILD_ID=dontKillMe

#java代码本地仓库地址

javaBaseSrc="/home/xiongshx/.jenkins/workspace/"

#项目路径

javaProjectSrc="seckill/seckill-web/target/seckill-web.war"

#发布的tomcat

projectServicersPath=(/opt/seckill-tomcat/seckill-tomcat-01)

projectName="sekill"

for var in ${PID};

do

  echo "准备强制中止PID:$var"

  kill -9 $var

done

echo "kill $serverName sucess"

#若是上一个命令执行失败,执行的状态码不为0

if [ $? -ne 0 ]

then

  echo "构建失败,请查看代码问题!"

  exit 1;

fi

for projectServicer in ${projectServicersPath[@]}

do

           cp $javaBaseSrc$javaProjectSrc $projectServicer/webapps

           echo "$projectServicer 代码发布成功!"

           /bin/bash $projectServicer/bin/startup.sh

           if [ $? -ne 0 ]

           then

             echo "$projectServicer 启动失败"

             exit 1;

           else

             echo "$projectServicer 启动成功";

           fi

done

echo "启动 $serverName 成功"

  三、 启动项目

  【当即构建】->【点击构建的连接】->【控制台输出】便可查看整个代码部署过程当中的信息输出。

 

 四、须要注意的问题点:

   一、Jenkins的war问题

    最简单jenkins.war的启动方式是在控制台终端执行命令:java -jar jenkins.war;可是此方法会占用一个终端窗口,且关闭后Jenkins工具就不能进行访问,可使用命令进行后台执行,命令以下:

  nohup java -jar jenkins.war --httpPort=9090 > /dev/null 2>&1 &

  命令解释

  nohup 后台执行操做

  --httpPort=9090表示指定占用9090端口进行访问

  > /dev/null 将日志输出到/dev/null

  2>&1 & 用来将标准错误2重定向到标准输出1中的此处1前面的&就是为了让bash将1解释成标准输出而不是文件1。最后一个&,则是让bash在后台执行

 

  另一种更优雅的方式是使用Shell脚本控制Jenkins工具的启动、中止、重启等操做。

  样例以下:

#!/bin/bash

#功能描述:用于Jenkins运行,中止,重启

#将此脚本放在jenkins.war同级目录

 

#获取Jenkins的进程id

pid=$(ps -ef| grep "jenkins.war" | grep -v grep | awk '{print $2}')

#jenkins默认端口号

jekinsDefaultPort=9090

#若是用户有自定义端口号,则使用用户自定义的端口号启动jenkins

if [ x$2 != x ]

then

   jekinsDefaultPort=$2

fi

 

#启动jenkins

start(){

       if [ x$pid != x ]

    then

              echo "jenkins已是启动状态..."

              exit 1

       fi

       nohup java -jar jenkins.war --httpPort=$jekinsDefaultPort > /dev/null 2>&1 &

       echo "jenkins启动成功,端口号为:$jekinsDefaultPort..."

       return $?

}

 

stop(){

       echo "准备中止jenkins..."

       if [ x$pid != x ]

        then

           kill -9 $pid

           echo "jenkins已经中止..."

           exit $?

       else

           echo "jenkins的进程id不存在,没法进行中止操做..."

           exit 1

       fi    

}

 

# 从新加载Jenkins

restart() {

    stop

    start

    echo "jenkins从新加载成功,jekins端口号为:$jekinsDefaultPort..."

}

 

case "$1" in

start)

        start

        ;;

stop)

        stop

        ;;

restart)

        stop

        start

        ;;

*)

        echo $"提示: 请在jenkins后输入如下参数:{start|stop|restart} 端口号(不填写时默认端口9090)"

        exit 1

esac

exit $?

  二、Jenkins中自定义Shell问题

    #须要在脚本开始时添加export BUILD_ID=dontKillMe。

    #缘由:由于Jenkins执行完当前任务以后须要执行下一个任务,此时Jenkins会直接把tomcat进程杀掉,#所以在脚本中编写的tomcat启动命令是不会执行的。

    export BUILD_ID=dontKillMe

【⑤课程总结及心得】

  学习代码自动部署的原因一来是因为在平时开发过程当中常常会遇到代码部署的环节,但愿经过学习此知识后,若是后续有机会针对本身学会的方案进行评估后简化项目中的项目部署,二来是巩固本身近期来学习到的一些知识,经过层层迭进来学习代码的自动部署方案。虽然目前本身的这些流程方案可能还有所欠缺,且尚未通过实际项目考验,但能学到不少实际的知识也足够了,好比Maven相关知识、Shell相关知识以及Jenkins相关知识,这些是只能经过本身动手慢慢去实践才能获取到的经验。若是对代码部署也感兴趣且以为我写的东西对你有帮助的同行们,我建议能够按照个人学习步骤去学习自动构建技术。

  此系列文章可能写的还不够好,而且不少地方我都进行了一些精简。其实我但愿给你们提供的是一个思路。好比学习整个项目部署的思路,由Maven插件部署到Shell脚本部署再到Jenkins部署项目,其实越到后面,Jenkins只是对一些操做作了集成封装,可是我以为若是咱们能从最基本作起,了解其中的流程及原理,真正使用Jenkins进行代码部署时,咱们能知道因此然,那样我以为能够更好的使用Jenkins工具。另外,好比Jenkins.war的启动,我很天然的想到使用Shell脚本将它的启动、运行、重启等命令进行封装,并把它设置为开机启动,我以为这是一个优雅的方式,之后有相似的状况时,我也会考虑这么作。

  本文中还有一些没有说起和没有实现的内容,我但愿以及对此技术感兴趣的同行们,均可以发散思惟,把事情尽善尽美,作到最优作好。经过编写此系列文章,我巩固了我此类技术的知识的了解以及拓展,也但愿可以帮助到你们。若是你们在学习此类技术上遇到疑惑或问题,能够百度查看解决办法,也能够给我留言进行探讨。

最后,但愿全部人在不久的未来都能遇到一个优秀的本身。