跳至主要內容
GitHub Actions 实战:Java 项目的 CI/CD 流水线搭建

GitHub Actions 实战:Java 项目的 CI/CD 流水线搭建

从零搭建一条完整的 Java 项目 CI/CD 流水线,包含编译、测试、代码扫描、Docker 镜像构建和多环境自动部署。

1. CI/CD 核心概念与价值

1.1 什么是 CI/CD

传统开发流程(无 CI/CD):

开发 → 本地测试 → 提交代码 → [等待] → 集成 → [发现冲突] → 排查 → 修复 →
手动构建 → 手动测试 → 手动部署 → [部署失败!] → 排查 → 重新部署
时间:数小时到数天


现代 CI/CD 流程:

开发 → 本地测试 → 提交代码 →
  ┌───────────────────────────────────────────────┐
  │              CI(持续集成)                      │
  │  自动检出 → 编译 → 单元测试 → 代码扫描 → 构建镜像  │
  │  时间:5-10 分钟                                │
  └───────────────┬───────────────────────────────┘
                  │ 全部通过
                  ▼
  ┌───────────────────────────────────────────────┐
  │              CD(持续交付/部署)                  │
  │  自动部署到 dev → 集成测试 → 部署到 staging →     │
  │  部署到 production(手动审批或自动)               │
  └───────────────────────────────────────────────┘

郑天祺大约 10 分钟CICDCICD
Jenkins 完全指南:从"又老又丑"到"CI/CD 常青树"

Jenkins 完全指南:从"又老又丑"到"CI/CD 常青树"

如果你问一个 10 年经验的后端:"十年前你们怎么部署代码?" 他八成会叹口气,然后说出那个让他又爱又恨的名字——Jenkins


一、用故事开头:Jenkins 到底是干嘛的?

想象一个场景:

凌晨 2 点,你刚写完最后一个功能。测试说 OK,前端说联调通过。现在你要——

  1. 拉最新代码
  2. 跑一遍测试
  3. 打个 war/jar 包
  4. 上传到服务器
  5. 停掉旧服务
  6. 启动新服务
  7. 确认部署成功
  8. 给群里发个通知

郑天祺大约 10 分钟CICDCICD
部署策略对比:蓝绿 vs 金丝雀 vs 滚动,怎么选

部署策略对比:蓝绿 vs 金丝雀 vs 滚动,怎么选

部署策略选错,轻则用户体验受损,重则生产事故。本文从原理到实践,帮你做出正确选择。

1. 四种主流部署策略图解

1.1 策略全景图

┌─────────────────────────────────────────────────────────────────┐
│                      四种部署策略对比                              │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  滚动更新(Rolling Update)                                      │
│  ┌───┐     ┌───┐     ┌───┐     ┌───┐                           │
│  │ v1 │ →  │ v2 │ →  │ v2 │ →  │ v2 │  逐个替换                   │
│  └───┘     └───┘     └───┘     └───┘                           │
│  ┌───┐     ┌───┐     ┌───┐     ┌───┐                           │
│  │ v1 │     │ v1 │ →  │ v2 │ →  │ v2 │                           │
│  └───┘     └───┘     └───┘     └───┘                           │
│  ┌───┐     ┌───┐     ┌───┐     ┌───┐                           │
│  │ v1 │     │ v1 │     │ v1 │ →  │ v2 │                           │
│  └───┘     └───┘     └───┘     └───┘                           │
│                                                                 │
│  蓝绿部署(Blue-Green)                                          │
│   ┌─────────────────┐         ┌─────────────────┐               │
│   │    Blue (v1)    │  切换 → │   Green (v2)    │               │
│   │   所有流量在这里    │ ──────→│   所有流量切过来   │               │
│   └─────────────────┘         └─────────────────┘               │
│                                                                 │
│  金丝雀发布(Canary)                                            │
│   流量: 90% v1  ──┐                                             │
│                  ├──→ 观察指标 → 10% OK → 50% → 100%             │
│   流量: 10% v2  ──┘                                             │
│                                                                 │
│  A/B 测试                                                        │
│   用户群A → v1 (对照组)                                          │
│   用户群B → v2 (实验组)  → 对比转化率/留存率                       │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

郑天祺大约 13 分钟CICDCICD
springboot打jar包分离资源文件

一、配置pom文件插件

    <build>
        <!-- jar包名 -->
        <finalName>${project.artifactId}</finalName>
        <plugins>
            <!-- 分离lib -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
                <version>2.8</version>
                <executions>
                    <execution>
                        <id>copy-dependencies</id>
                        <phase>package</phase>
                        <goals>
                            <goal>copy-dependencies</goal>
                        </goals>
                        <configuration>
                            <!-- 依赖包输出目录,将来不打进jar包里 -->
                            <outputDirectory>${project.build.directory}/lib</outputDirectory>
                            <excludeTransitive>false</excludeTransitive>
                            <stripVersion>false</stripVersion>
                            <includeScope>runtime</includeScope>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            <!-- copy资源文件 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-resources-plugin</artifactId>
                <version>3.3.0</version>
                <executions>
                    <execution>
                        <id>copy-resources</id>
                        <phase>package</phase>
                        <goals>
                            <goal>copy-resources</goal>
                        </goals>
                        <configuration>
                            <resources>
                                <resource>
                                    <directory>src/main/resources</directory>
                                </resource>
                            </resources>
                            <outputDirectory>${project.build.directory}/resources</outputDirectory>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            <!-- 打jar包时忽略配置文件 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <version>2.4</version>
                <configuration>
                    <excludes>
                        <exclude>**/*.yml</exclude>
                        <exclude>**/*.xml</exclude>
                    </excludes>
                </configuration>
            </plugin>
            <!-- spring boot repackage -->
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>2.6.0</version>
                <configuration>
                    <layout>ZIP</layout>
                    <includes>
                        <include>
                            <groupId>non-exists</groupId>
                            <artifactId>non-exists</artifactId>
                        </include>
                    </includes>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <!-- maven 打包时跳过测试 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.12.4</version>
                <configuration>
                    <skip>true</skip>
                </configuration>
            </plugin>
        </plugins>
    </build>

郑天祺大约 2 分钟CICDSpringBoot打包运维
软件安装及高可用部署(三)

本文介绍了MYSQL安装

一、卸载mariadb

# 查看 mariadb 的安装包
rpm -qa | grep mariadb
# 卸载 mariadb 的安装包
rpm -e mariadb-libs-5.5.68-1.el7.x86_64 --nodeps
# 再次查看
rpm -qa | grep mariadb

郑天祺大约 7 分钟CICD运维部署高可用
软件安装及高可用部署(二)

本文介绍了Nginx安装

一、修改主机名

以 nginx-master 为例,修改所有服务器的对应的主机名。

vim /etc/hostname
# 删除所有的内容,修改为要修改的主机名
nginx01
vim /etc/hosts
#在第一行最后追加主机名,有127.0.0.1内容的这行
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
nginx01
# 重启服务器
reboot

郑天祺大约 3 分钟CICD高可用部署运维
软件安装及高可用部署(一)

本文介绍了磁盘挂载、JDK安装、Keepalived安装

一、硬盘挂载

(1)查看设备的挂载情况

lsblk或lsblk –f或者fdisk -l
img
img

(2)分区

fdisk /dev/vdb 其中/dev/vdb表示上图未挂载的硬盘
分区步骤如下图,下图以/dev/sdb为例
img
img
img


郑天祺大约 2 分钟CICD运维部署高可用Keepalived
nginx配置

一、负载均衡策略

负载均衡用于从“upstream”模块定义的后端服务器列表中选取一台服务器接受用户的请求。一个最基本的upstream模块是这样的,模块内的server是服务器列表:

#动态服务器组
upstream dynamic_zuoyu {
    server localhost:8080;  #tomcat1
    server localhost:8081;  #tomcat2
    server localhost:8082;  #tomcat3
    server localhost:8083;  #tomcat4
}

郑天祺大约 12 分钟CICDNginx负载均衡配置
Docker网络模型

Docker虚拟化技术底层是基于LXC+Cgroups+AUFS(Overlay)技术实现,而我们有熟知Cgroups是Linux内核提供的一种可以限制、记录、隔离进程组(Process Groups)所使用的物理资源的机制。
Docker虚拟化的产物是Docker容器,基于Docker Engine启动容器时,默认会给容器指定和分配各种子系统:CPU子系统、Memory子系统、IO子系统、NET子系统等。
启动一个容器,会分配Network Namespace(子系统)提供了一份独立的网络环境,包括网卡、路由、Iptables规则等,容器跟其他容器的Network Namespace是相互隔离的。
通过Docker run创建Docker容器时,可以使用–net选项指定Docker容器的网络模式,Docker默认有四种网络模式:


郑天祺大约 7 分钟CICDDocker网络模型容器化
2