tangtang's blog

A gamer, a programmer.

自动化部署成果和测试

由头

这两天看了一些自动化部署的方案,就想着把自己公司的部署方式搞成自动化的。其实还是自己懒,实在不想每次都打好包再远程服务器去替换、重启。

这里得说一下前提,因为历史原因,公司服务器用的阿里云,且是Windows系统(好烦啊,为啥不买Linux的)。
项目结构也简单,后端就一个,SpringBoot框架的,打包出来是个jar,我在服务器上写个bat文件直接java -jar就完事儿。
前端有好几个东西,包含微信的H5、web端的管理平台、公司的宣传网站。
因为业务量也不大,所以用不着分布式啥的。就直接一个nginx映射几个成几个子域名,后端接口也通过nginx映射后供前端页面调用。

总结一下现在更新方式:
1. 后端更新:直接本地打jar包->远程服务器->停服务->备份旧jar包->拷贝新jar包->起服务
2. 前端更新:前端妹子打好包(Vue开发的,就是个dist.rar)发我->本地解压改名->远程服务器->备份旧的前端文件->替换成新的

实现方式

业务比较简单,也用不着啥Jenkins这些持续集成啥的东西了,就Git Hook应该满足需求。
我现在在自己的阿里云服务器(CentOS)上试Git Hook,等成功了再搞公司服务器去。
先写到这边。

结果

折腾了好几天,最终还是优先对自己的Java后端项目做了自动化部署的处理。下面总结几点:

  • 使用的是Gradle,所以选择了gradle-ssh-plugin插件来辅助完成
  • 公司服务器是Windows平台,所以需要额外安装ssh服务

下面给出我的gradle-ssh-plugin这个插件的使用示例:

  1. 引入插件
    在build.gradle中,引入插件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    buildscript {
    ext {
    springBootVersion = '2.1.1.RELEASE'
    sshPluginVersion = '2.10.1'
    }
    repositories {
    maven {
    url 'http://maven.aliyun.com/nexus/content/groups/public/'
    }
    mavenCentral()
    }
    dependencies {
    classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
    classpath("org.hidetake:gradle-ssh-plugin:${sshPluginVersion}")
    }
    }


    apply plugin: 'org.hidetake.ssh'
  2. 配置远程地址信息

    仍然是在build.gradle中编写:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    ssh.settings {
    //支持多服务器部署(一般用于集群)
    knownHosts = allowAnyHosts
    }

    //远程服务器信息
    remotes {
    //这个deployServer名字是自定义的,可以配置多台服务器
    deployServer {
    host = '192.168.0.163'
    user = 'Administrator'
    // 支持password、rsa等方式登录
    password = '123456'
    //identity = file("${rootDir}/id_rsa")
    }
    testServer{
    host = '192.168.0.165'
    user = 'root'
    // 支持password、rsa等方式登录
    password = '123456'
    //identity = file("${rootDir}/id_rsa")
    }
    }
  3. Gradle任务编写

    最后就是编写你的部署逻辑啦。这个会因为每个项目技术栈的不同,服务器的环境不同,可能会有各种细节上的出入,但逻辑还是可以参考的。当然,也可以Google一下跟自己类似的部署方案是什么逻辑。
    一般部署逻辑无外乎:停止服务->备份上一版本->传输新部署包->
    重启服务,如果是tomcat下部署,那可能涉及解压等等其他操作,这些都可以通过shell命令去完成,这里就不赘述了。我这里的shell命令示例基于我自己的服务器情况,服务器环境是Windows,已经安装了Cygwin(让Windows平台下可以运行shell命令,支持ssh插件),项目是SpringBoot项目,Gradle构建,直接在开发机器上打成jar包,在服务器上直接使用java
    -jar xxxx.jar命令来启动。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31

    // 定义一个获取当前时间字符串的辅助函数
    static def now() {
    new Date().format('yyyyMMddHHmmss')
    }

    // 定一个pkg任务
    task pkg
    pkg.dependsOn 'clean'
    pkg.dependsOn 'bootJar'
    bootJar.shouldRunAfter 'clean'
    // 定义自动部署脚本
    task deploy(dependsOn: pkg) {
    doLast {
    println("start task deploy:${now()}")
    ssh.run {
    session(remotes.deployServer) {
    // 停止原有服务
    execute '/cygdrive/c/winsw/stop.bat'
    // 备份原有程序,首次部署mv会执行失败,忽略错误
    execute "mv /cygdrive/c/winsw/saas.jar /cygdrive/c/winsw/backup/saas.${now()}", ignoreError: true
    // 上传新版本程序
    put from: 'build/libs/freelycar_saas-' + version + '.jar', into: '/cygdrive/c/winsw/saas.jar'
    // 赋予可执行权限
    // execute 'chmod u+x /cygdrive/c/winsw/saas.jar'
    // 启动新服务
    execute '/cygdrive/c/winsw/start.bat'
    }
    }
    }
    }

这样gradle中就多了两个自定义任务,名字分别为pkg和deploy的task任务,并且deploy依赖于pkg的成功。
pkg任务其实就是执行了gradle自带的clean(清理)和bootJar(打jar包)任务,成功后执行deploy任务。

以上就是我的自动化部署的一种实现方式。其实这段时间也是稍微试了一下Jenkins,后面如果用起来了再总结一下Jenkins的使用感受吧。
如果有疑问,欢迎大家留言,我会不定期回复的。

简单两句

这两天手上项目不忙了,抽空把自己的博客搞一搞。主要更新了一下Hexo以及NexT主题。

我发现NexT主题升到7.x以后,配置文件中集成了不少好的配置项,确实很赞。比如说备案号的设置、头像的旋转、回到顶部显示百分比等等。

博客目前效果上就先这样吧。我去掉了背景图片这些花里胡哨的玩意儿,希望看上去清爽点。

后续计划

我想后面博客内容暂定是偏向电脑知识以及游戏动漫的个人向推荐。如果到时候有人看,并且觉得有意思的话,我会多考虑如何写出博友喜欢看的东西的。

形式上我会做两种尝试,一种是像这篇一样,每一段话短小简介,贴近微博那种形式。另一种就是传统文章,每一段篇幅合适。

结束语

南京快要实行垃圾分类了,不知道你们的城市是不是也开始了呢?(喂,你还没加评论系统啊喂!)

ps:评论系统这周内加上~嗯!应该吧!

写在前面

其实自己一直都很懒,宁可折腾一些没有价值的代码,也懒得去写几行文字。

关于生日

今年的生日过了,也就是前几天。特意推掉了健身,喊上了小伙伴,一起去吃了顿烤鱼。关于烤鱼,也是纠结了很久才确定的。感觉周围的美食,要么是吃腻了,要么是不想吃。

每次过生日都会紧张,害怕别人来祝福,不知道应该回复什么,最常回的也就是句“谢谢”。跟慕慕说起来的时候,她就宽慰我说:“生日也就是普通的一天,不用紧张。”而事实上,我也不再会想大了一岁还是老了一岁怎么怎么样了。

关于随笔

是有很久一段时间不写随笔了。上一次保留这个习惯的阶段,应该要算高中了。大学四年、工作四年,八年来可能快乐的时光居多,也可能是成人世界工作所累,平时闲下来都是忙着玩我最爱的游戏,所以并不想花时间用文字记录什么。

今天正好翻看了Google相簿,发现自动上传的一些照片,有大学时抄写的笔记、玩的游戏,有毕业后上的培训班试题、一起上课的同学,还有陪外婆在院子里拾掇“扭扭菜”时外婆的那张照片
。那些都是14、15年的,感觉如此陌生,又如此熟悉。

不得不感慨时间过得真快。以后我还是会不时地写一些东西吧,不论是随笔,还是编程方面的知识点,甚至是时评、生活趣事儿等等。因为我不喜欢拍视频,也不喜欢给自己和身边的人拍照,但我想我的文章里可以采用配图的形式。或许配上图片,以后回头看看也是不错的。

至于微博,我并不喜欢那种交流方式,可能还是博客适合我。我喜欢的是观察者,而不是讨论者。

关于以后

我还记得上一家公司每半年要写工作总结,里面每次都需要写一些未来规划。我们这里先不讨论这个的实用性,也不讨论规划会不会完全按着来的问题。这里我写一些对自己以后的规划。

首先是工作上。现在在这家单位,项目上我负责的最多,后端开发也是我主要负责。那么在工作能力上,项目管理的学习是第一位,后台架构的知识巩固是第二位。《软件项目管理》这本书已经买了有两周了,我还没翻开来看过。既然在家看不进去书,那就在单位每天看点吧。

其次是生活上。希望自己能更多的陪陪家里人,不仅仅是老婆,还有外婆和爸妈。希望距离上照顾不到的,我能够从心理上多陪陪他们。

对了,还有我家里的两个小东西——斑斑和球球,这俩小家伙已经一岁半了,希望它们能陪我久一些。最后附上最近斑斑和球球的照片(后面可能会做一期它们的专题)。

球球&斑斑

去年10月底的时候我也是尝试用Hexo+Github的形式去搭建了自己的博客。说实话,还是很好用的。但后来由于工作上的一些原因,并没有开始写博客。这次搭建希望能开始写一些博客,并把自己博客的主题弄得『炫』一些。
先弄一篇博客试试,可以的话就开始弄主题去了。这次应该会使用Next主题吧,毕竟网上推荐的人不少。
就写到这儿吧。

附上一张Gakki图,测试一下Markdown的图片引用:
Gakki

0%