Java代码自动部署

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

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

如果想学习Java工程化、高性能及分布式、深入浅出。微服务、Spring,MyBatis,Netty源码分析的朋友可以加我的Java高级交流:854630135,群里有阿里大牛直播讲解技术,以及Java大型互联网技术的视频免费分享给大家。

由于本人近期在学习Java代码自动发布相关的知识,此系列文章是对此次学习到的知识进行巩固和总结;同时,也希望能够帮助到和我一样对此方面知识感兴趣的同行们。言不多说,直接进入真题。下面针对此次系列文章做一个简要的概述。

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

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

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

1、 CentOS操作系统(可以使用虚拟机安装Linux系统)

2、 Maven

3、 Git

4、 Shell脚本

5、 Jenkins

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

阶段1:

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

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

阶段2:

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

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

阶段3:

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

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

4、Java代码自动部署总结分为以下系列

①总结简介

②使用Maven进行代码部署

③使用Shell进行代码部署

④使用Jenkins进行代码部署

⑤课程总结及心得

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

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

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

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

1) 项目本身属于Maven项目(必要条件)

2) 需要部署的是war包

3) 引入插件

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

org.apache.tomcat.maven


tomcat7-maven-plugin


http://192.168.25.133:8080/manager/text


admin


admin


8080

/seckill-manager

UTF-8

UTF-8

4) 执行Maven的redeploy操作

执行的命令:tomcat7:redeploy

在eclipse下配置的命令如下:

2、需要注意的问题点

1、在将项目发布到远程Tomcat时需要启动远程Tomcat管理控制台账号

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

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

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

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

Tomcat角色解释图:

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

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

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

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

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

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

环境要求:

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

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

3、 熟悉Shell脚本相关知识

1、编写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 成功"

2、需要注意的问题点

在编写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进行代码部署】

如果想学习Java工程化、高性能及分布式、深入浅出。微服务、Spring,MyBatis,Netty源码分析的朋友可以加我的Java高级交流:854630135,群里有阿里大牛直播讲解技术,以及Java大型互联网技术的视频免费分享给大家。

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

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

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

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

3、熟悉Shell脚本相关知识

4、对Jenkins有一定了解

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

1、 启动Jenkins工具

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

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

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

初始化后需要进行的配置

工具配置

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

Jdk配置:

Git配置:

Maven配置:

2、 新建任务

需要注意的点:

1、填写源码仓库地址

2、构建时操作及自定义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 成功"

3、 启动项目

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

 4、需要注意的问题点:

1、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在后台执行。

如果想学习Java工程化、高性能及分布式、深入浅出。微服务、Spring,MyBatis,Netty源码分析的朋友可以加我的Java高级交流:854630135,群里有阿里大牛直播讲解技术,以及Java大型互联网技术的视频免费分享给大家。

另外一种更优雅的方式是使用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 $?

2、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脚本将它的启动、运行、重启等命令进行封装,并把它设置为开机启动,我觉得这是一个优雅的方式,以后有类似的情况时,我也会考虑这么做。

本文中还有一些没有提及和没有实现的内容,我希望以及对此技术感兴趣的同行们,都可以发散思维,把事情尽善尽美,做到最优做好。通过编写此系列文章,我巩固了我此类技术的知识的了解以及拓展,也希望能够帮助到大家。如果大家在学习此类技术上遇到疑惑或问题,可以百度查看解决办法,也可以给我留言进行探讨。

如果想学习Java工程化、高性能及分布式、深入浅出。微服务、Spring,MyBatis,Netty源码分析的朋友可以加我的Java高级交流:854630135,群里有阿里大牛直播讲解技术,以及Java大型互联网技术的视频免费分享给大家。

最后,希望所有人在不久的将来都能遇到一个优秀的自己。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,560评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,104评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,297评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,869评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,275评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,563评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,833评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,543评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,245评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,512评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,011评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,359评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,006评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,062评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,825评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,590评论 2 273
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,501评论 2 268

推荐阅读更多精彩内容