最近业余搞了一堆JAVA项目,每次都是手动git push再pull、编译打包运行,感觉很low。

尤其买了一堆各个区域的云服务器,规模一扩大,手动运维的效率急剧下降。

这个博客站点其实用的是Github Action自动触发编译部署,我把本文在本机写好,git push即可完成发布。

因此,JAVA相关项目我也准备使用CI工具自动部署和运维。本人之前也做了好几年SRE,另外阿里云效也和每天操作的公司内部CI工具类似,所以上手很快。

JAVA工程MVN配置

JAVA工程结构为

gateway

|-starter

|-tb

其中启动类在starter中,tb里面主要是业务逻辑。

尝试了一些打包插件,但发现执行starter打出的jar执行后并不包含tb模块。

因此使用maven-shade-plugin作为打包插件。

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
32
33
34
35
36
37
38
39
40
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</path>
</annotationProcessorPaths>
<skip>true</skip>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<executions>
<execution>
<id>shade-jar-with-dependencies</id>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<finalName>starter</finalName>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<manifestEntries>
<Main-Class>com.project256.iot.gateway.Application</Main-Class>
</manifestEntries>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>

finalName为starter是为了指定输出jar包的文件名,避免包版本升级后,部署脚本也得跟着改。

Main-Class指定启动入口类,避免找不到启动类的情况。

部署脚本编写

让大模型帮我写,描述清楚需求即可。

虽然杀死进程不是很优雅,先用着。

1
2
3
4
5
我通过持续集成工具,将starter.jar部署到/root/app文件夹
但我需要通过deploy.sh停止已经启动的服务,并后台运行java -jar starter.jar
类似nohup,在日志文件中输出日志

请编写deploy.sh

得到脚本,命名为deploy.sh

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
#!/bin/bash

# 设置变量
APP_NAME="starter"
JAR_PATH="/root/app/starter.jar"
LOG_FILE="/root/app/starter.log"

# 停止已运行的服务
echo "Stopping existing $APP_NAME service..."

# 查找正在运行的 Java 进程并杀死它
PID=$(pgrep -f $APP_NAME)
if [ -n "$PID" ]; then
echo "Found running $APP_NAME with PID: $PID. Stopping it..."
kill -9 $PID
echo "$APP_NAME stopped."
else
echo "$APP_NAME is not running."
fi

# 启动新的服务
echo "Starting $APP_NAME service..."
nohup java -jar $JAR_PATH >> $LOG_FILE 2>&1 &

# 输出启动信息
echo "$APP_NAME started. Logs are being written to $LOG_FILE."

将其放置到starter模块的resources文件夹下,当然也可以放到其他文件夹,由CI工具进行复制并执行。

配置云效代码库

云效拉取Github过于缓慢,10分钟都拉不下来阻塞后续流程,而拉取耗时也走资源用量(每月会送3000核分)。

因此将Github代码同步一份到代码管理中,并配置.git/config,当执行git push时自动双推。

导入代码库
导入代码库

具体操作看官方文档即可,再把本机的rsa公钥配置到云效代码库中。

.git/config配置如下 ,在remote “origin”下方配置两个目标url。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
ignorecase = true
precomposeunicode = true
[remote "origin"]
url = git@github.com:SUTFutureCoder/XXX.git
url = git@codeup.aliyun.com:xxx/SUTFutureCoder/XXX.git
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "main"]
remote = origin
merge = refs/heads/main

配置流水线

可以选择包含构建上传和主机部署的流程模板,后续把代码扫描和单元测试删掉即可。

新建流水线
新建流水线

注意修改构建上传的配置,将脚本复制进打包路径中,默认的配置会报错。

构建配置
构建配置

JAVA构建上传的产物,能够通过不同策略部署到单台或多台机器上。

由于是个人开发、部署单台服务器,所以不用什么SOP,直接无脑不暂停即可。

当多人开发、部署集群时,操作SOP和灰度、回滚策略就需要考虑了。

主机直接按照指引执行命令注册即可。

主机部署
主机部署

登录机器观察

登录机器后,查看app目录,观察jar包、脚本是否被正确部署。

观察部署结果
观察部署结果

总结

相比于自建Jenkins,对于个人项目使用云服务就足够了。

编译成Docker镜像也可以,但对于个人小项目有点大炮打蚊子了。

流水线的Webhook触发运行不推荐使用,除非能确保每次推送代码都不会出错,这种触发方式和无脑一把梭没什么区别。