1. 工具介绍

git:版本控制,一般都是托管到代码仓库的。如 github、coding、gitlab (本文以 coding 为例)

jenkins:持续集成工具之一,也是最常用的工具,主要工作就是将代码从git仓库pull下来,通过maven打包,在部署到服务器上

maven:java 项目管理构建自动化工具,主要是将 java 源代码打包成 jar 程序

ansible:批量部署程序所使用的工具。

下面介绍的部署过程使用到了以上 4 个工具。

主机介绍:

实现思路:

2. 持续集成实例

2.1 首先将源代码托管到 git 仓库,具体操作自行百度,例如:coding仓库。

我这里是一个私有仓库,请自行创建仓库。

2.2 安装 jenkins 和 maven 工具

【jenkins 安装过程】

这里最好将 jenkins 配置文件修改如下:

[root@192.168.118.17 ~]#vim /etc/sysconfig/jenkins
...
JENKINS_USER="root"
...

修改为 root 这样可以直接使用 root用户打包,不用在其他用户家目录下构建依赖包

本次构建使用了 jenkins 的 pipeline 功能,这里需要安装一些插件:

系统管理 -> 插件管理 -> 可选插件  搜索一下插件进行安装:

Blue Ocean

插件安装完成后,重启下服务:

[root@192.168.118.17 ~]#systemctl restart jenkins

安装 git 和 maven

安装git

[root@192.168.118.17 ~]#yum install git -y

安装 maven

下载地址:http://maven.apache.org/download.cgi
[root@192.168.118.17 /usr/local/src]#tar xf apache-maven-3.1.1-bin.tar.gz -C /usr/local/
[root@192.168.118.17 /usr/local/src]#cd /usr/local/
[root@192.168.118.17 /usr/local]#ln -vs /usr/local/apache-maven-3.1.1/ /usr/local/maven
‘/usr/local/maven’ -> ‘/usr/local/apache-maven-3.1.1/’ [root@192.168.118.17 /usr/local]#ln -vs /usr/local/maven/bin/mvn /usr/bin/
‘/usr/bin/mvn’ -> ‘/usr/local/maven/bin/mvn’

安装好两个工具后,首先通过 git 将源代码克隆下来,通过 maven 进行测试。

[root@192.168.118.17 ~]#git clone https://git.dev.tencent.com/hukey/winstar-common-api.git
[root@192.168.118.17 ~]#cd winstar-common-api/
[root@192.168.118.17 ~/winstar-common-api]#mvn clean package -Dmaven.test.skip=true

第一次通过 mvn 打包时间会长一点。

出现如上信息,则打包完成。

2.3 通过 ansible 将程序推送到需要部署的节点

接下来的思路:

  通过 ansible 将 xxx.jar 文件推送到需要部署的服务器上,启动起来。

安装 ansible 并配置:

[root@192.168.118.17 ~]#yum install ansible -y

(1)将 ansible 主机连接 程序部署主机设置为免密码登录

[root@192.168.118.17 ~]#ssh-keygen -t rsa -P ''
[root@192.168.118.17 ~]#ssh-copy-id root@192.168.118.19
[root@192.168.118.17 ~]#ssh-copy-id root@192.168.118.20

(2)配置 ansible 组

[root@192.168.118.17 ~]#vim /etc/ansible/hosts
...
[common-api]
192.168.118.19:22 ansible_ssh_user=root adrser=/app/node-1/
192.168.118.20:22 ansible_ssh_user=root adrser=/app/node-1/
...

格式:
ip:port ansible_ssh_user=用户名 adrser=设置一个变量,这里设置的变量为一个程序部署目录,这两台主机目录必须存在。

(3)测试 ansible 无密码验证

[root@192.168.118.17 ~]#ansible common-api -m ping
192.168.118.20 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}
192.168.118.19 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}

(4)通过 ansible 为两台程序节点部署环境

创建启动程序目录:
[root@192.168.118.17 ~]#ansible common-api -m file  -a "path=/app/node-1 state=directory"
192.168.118.19 | SUCCESS => {
    "changed": true,
    "gid": 0,
    "group": "root",
    "mode": "0755",
    "owner": "root",
    "path": "/app/node-1",
    "size": 6,
    "state": "directory",
    "uid": 0
}
192.168.118.20 | SUCCESS => {
    "changed": true,
    "gid": 0,
    "group": "root",
    "mode": "0755",
    "owner": "root",
    "path": "/app/node-1",
    "size": 6,
    "state": "directory",
    "uid": 0
}

为两台程序节点安装jdk

# 将jdk拷贝到远程主机,并解压到 /usr/local/ 目录
[root@192.168.118.17 ~]#ansible common-api -m unarchive -a "src=/usr/local/src/jdk-8u77-linux-x64.tar.gz dest=/usr/local/" # 创建软链接文件
[root@192.168.118.17 ~]#ansible common-api -m file -a "path=/usr/bin/java src=/usr/local/jdk1.8.0_77/bin/java state=link" [root@192.168.118.17 ~]#ansible common-api -m file -a "path=/usr/bin/javac src=/usr/local/jdk1.8.0_77/bin/javac state=link"

(5)首先将 jar 包推送到两台服务器上,是为了编写启动脚本比较方便。

[root@192.168.118.17 ~]#ansible common-api -m copy -a "src=/root/winstar-common-api/target/winstar-common-api-1.0.0-SNAPSHOT.jar dest={{adrser}}"

(6)编写程序启动脚本

[root@192.168.118.19 /app/node-1]#vim service.sh
#!/bin/bash
cd /app/node-1
start(){
  if [ -f `ls *.jar` ];then
    APP=$(ls *.jar)
    nohup java -jar $APP &
  else
    echo "Error: no app!"
  fi
} stop(){
  pkill -9 java
} update(){
  if [ ! -d backup ];then
    mkdir -p backup
  fi
  mv -f *.jar backup
  rm -rf nohup.out
} case $1 in
start)
  start
  ;;
stop)
  stop
  ;;
update)
  stop
  update
  ;;
*)
  echo "Usage: $0 [start | stop | update]"
esac

编写了一个比较简单的脚本,这个脚本只是用来测试使用,如果生产环境使用,还有许多地方需要进行改善。

将这个脚本放在两个程序节点 /app/node-1/目录下。

(7)通过 ansible 测试程序能否正常启动成功

第一步,将程序从控制节点拷贝到程序节点:

# 安装 net-tools 包,主要用到 netstat 命令
[root@192.168.118.17 ~]#ansible common-api -m yum -a "name=net-tools state=present"
# 查看目前在工作的端口信息
[root@192.168.118.17 ~]#ansible common-api  -a "netstat -ntplu"
192.168.118.19 | SUCCESS | rc=0 >>
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      891/sshd            
tcp        0      0 127.0.0.1:25            0.0.0.0:*               LISTEN      1454/master        
tcp6       0      0 :::22                   :::*                    LISTEN      891/sshd            
tcp6       0      0 ::1:25                  :::*                    LISTEN      1454/master         192.168.118.20 | SUCCESS | rc=0 >>
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      882/sshd            
tcp        0      0 127.0.0.1:25            0.0.0.0:*               LISTEN      1369/master        
tcp6       0      0 :::22                   :::*                    LISTEN      882/sshd            
tcp6       0      0 ::1:25                  :::*                    LISTEN      1369/master # 将应用程序拷贝到程序节点
[root@192.168.118.17 ~]#ansible common-api -m copy -a "src=/root/winstar-common-api/target/winstar-common-api-1.0.0-SNAPSHOT.jar dest={{adrser}}"

第二步,启动程序,查看程序端口

# 启动应用程序
[root@192.168.118.17 ~]#ansible common-api  -a "sh {{adrser}}/service.sh start"
# 启动完毕间隔一段时间,查看应用程序端口是否启动完成
[root@192.168.118.17 ~]#ansible common-api  -a "netstat -ntplu"
192.168.118.19 | SUCCESS | rc=0 >>
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      891/sshd            
tcp        0      0 127.0.0.1:25            0.0.0.0:*               LISTEN      1454/master        
tcp6       0      0 :::3090                 :::*                    LISTEN      3447/java          
tcp6       0      0 :::3091                 :::*                    LISTEN      3447/java          
tcp6       0      0 :::22                   :::*                    LISTEN      891/sshd            
tcp6       0      0 ::1:25                  :::*                    LISTEN      1454/master         192.168.118.20 | SUCCESS | rc=0 >>
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      882/sshd            
tcp        0      0 127.0.0.1:25            0.0.0.0:*               LISTEN      1369/master        
tcp6       0      0 :::3090                 :::*                    LISTEN      3200/java          
tcp6       0      0 :::3091                 :::*                    LISTEN      3200/java          
tcp6       0      0 :::22                   :::*                    LISTEN      882/sshd            
tcp6       0      0 ::1:25                  :::*                    LISTEN      1369/master

应用端口:3090,管理端口:3091 说明启动成功。

至于 stop 和 update 可以自行测试,必须要保证脚本的可用性,因为后面会用到。

2.4 配置 jenkins pipeline流水线

登录 jenkins -> 新建任务

应用并保存,这样 jenkins 配置已经完成。要使用 jenkins 的 pipeline 功能,要需要在 git 仓库里新增几个配置文件。

2.5 在 git 仓库配置 pipeline 文件

登录到仓库页面

Jenkinsfile 文件内容如下:

pipeline{
    agent any
    stages {
        stage('Build') {
            steps{
                sh 'mvn clean package -Dmaven.test.skip=true'
                echo 'Build success.'
            }
        }
        stage('Test') {
            steps{
                sh 'mvn test'
            }
            post {
                always {
                    junit 'target/surefire-reports/*.xml'
                }
            }
        }
        stage('Deliver') {
            steps {
                sh 'sh ./jenkins/scripts/deliver.sh'
            }
        }
    }
}

代码内容很简单,分为三段:

1. 打包
2. 测试
3. 发布

重点关注下 第三个 发布是通过出一个脚本来实现的。因此这个目录和脚本必须也放置到 git 仓库。 将 jenkins pipeline 配置文件和脚本放置到 git仓库,这样更易于维护,而且对 jenkins 的使用会更加灵活。

注意脚本放置的目录,脚本内容如下:

#!/bin/bash
# Author: hukey
# date: 2019-07-16 17:23:20
#
function status(){
ansible common-api -a "netstat -ntplu"
} function update(){
  if [ ! -f target/*.jar ];then
      echo '[Error]:java.jar not exist, update failed.'
      exit 1
  fi
  JAR=$(ls target/*.jar)
  ansible 'common-api' -m shell -a '{{adrser}}/service.sh update'
  ansible 'common-api' -m copy -a "src=$JAR dest={{adrser}}"
} function start(){
  ansible 'common-api' -m shell -a '{{adrser}}/service.sh start'
} update
sleep 3
start

上面的脚本,必须和 app-node 中的脚本对应着来看,简要说下:

首先 执行 update 操作,将 app-node 上的应用程序停止并备份到backup目录,将本地的 jar 程序拷贝到 app-node 节点;

再次 通过 start 将 app-node 上的程序启动起来。

这样一个持续性的流水线工作就完成了。

3. 持续集成测试

点击构建,然后查看后台日志输出信息:

当返回 SUCCESS 说明构建成功了。也可以通过 Blue Ocean 查看

到这里, 采用 jenkins 构建 java 项目持续集成已经完毕,这里采用的是手动触发构建,如果需要自动构建可以通过 webHook 来实现。

最新文章

  1. CSS3中的动画效果记录
  2. android Activity介绍
  3. 自定义view文字垂直居中
  4. SPI
  5. Linux Process Virtual Memory
  6. spring事务学习(转账案例)(二)
  7. ViewState压缩
  8. 常用的Eclipse快捷键
  9. 诡异的_DEBUG宏
  10. Saiku如何固定查询结果table的表头和首列
  11. HTML5 DTD
  12. Oracle数据库案例整理-Oracle系统执行时故障-Shared Pool内存不足导致数据库响应缓慢
  13. 并串转换FPGA电路结构的探讨
  14. OpenCV探索之路(二十六):如何去除票据上的印章
  15. 一句Python,一句R︱pandas模块——高级版data.frame
  16. vijos 1512 SuperBrother打鼹鼠
  17. 安卓基础之Sqlite数据库最最基础操作
  18. Java Junit 基础笔记
  19. Exce行列变色
  20. vue + element ui 阻止表单输入框回车刷新页面

热门文章

  1. tensorflow LSTM+CTC使用详解
  2. Java获取视频的大小、时长
  3. C++ 类的静态成员
  4. MySQL 效率提高N倍的19条MySQL优化秘籍
  5. MyBatis项目配置案例详解与Web下的增删改查实现[附项目源码]
  6. Ubuntu16.04 配置vnc4server
  7. go的flag模块使用例子
  8. Oracle的存储的三大物理文件
  9. Check if List<Int32> values are consecutive
  10. I.MX6 dts 在哪里、怎么编译【转】