实战案例:微服务多模块项目、全栈构建脚本、CI/CD流水线、性能调优总结
终于到了最后一章。说实话,写到这里我挺感慨的。前面二十九章我们聊了 Gradle 的方方面面,从基础语法到高级技巧,从依赖管理到性能优化。但我知道,大家最想看的还是——这些东西到底怎么用在一个真实项目里?
好,那我们就拿一个典型的微服务项目来开刀。这个案例我去年在给一家电商公司做咨询时亲手搭过,后来成了他们内部的标准模板。今天我把核心思路拆给你看。
项目结构:多模块怎么分
先看整体布局。一个微服务项目,模块划分是第一步。我个人习惯按业务领域来切,而不是按技术层来切。你想想看,如果按 controller、service、dao 来分模块,那每个微服务都得重复建一套,累不累?
project-root/
├── build.gradle.kts # 根项目脚本
├── settings.gradle.kts # 模块声明
├── gradle.properties # 全局属性
├── gradle/
│ └── libs.versions.toml # 版本目录
├── common/ # 公共模块
│ ├── common-core/ # 基础工具类
│ ├── common-web/ # Web 通用配置
│ └── common-security/ # 安全认证
├── services/ # 业务服务
│ ├── user-service/
│ ├── order-service/
│ └── payment-service/
└── deploy/ # 部署相关
├── docker-compose/
└── k8s/
这里有个关键点:common 模块只放真正公用的东西。我在项目中遇到过有人把整个工具包都塞进 common,结果每个微服务都依赖它,一改就全炸。记住,common 越轻量越好。
全栈构建脚本:从开发到部署
根项目的 build.gradle.kts 我一般只做两件事:配置插件和定义子项目通用行为。
// 根项目 build.gradle.kts
plugins {
id("org.springframework.boot") version "3.2.0" apply false
id("io.spring.dependency-management") version "1.1.4" apply false
id("com.google.cloud.tools.jib") version "3.4.0" apply false
}
subprojects {
apply(plugin = "java")
apply(plugin = "io.spring.dependency-management")
group = "com.example"
version = "1.0.0"
java {
toolchain {
languageVersion = JavaLanguageVersion.of(17)
}
}
tasks.withType<Test> {
useJUnitPlatform()
}
}
看到 apply false 了吗?这是关键。根项目只声明插件,不应用。子项目按需选择。比如 user-service 需要 Spring Boot,那就自己 apply。
版本目录:统一依赖管理
我用 libs.versions.toml 来管所有依赖版本。这玩意儿比 ext 块好用多了。
# gradle/libs.versions.toml
[versions]
spring-boot = "3.2.0"
spring-cloud = "2023.0.0"
mybatis-plus = "3.5.5"
redisson = "3.27.0"
[libraries]
spring-boot-starter-web = { module = "org.springframework.boot:spring-boot-starter-web" }
spring-boot-starter-data-redis = { module = "org.springframework.boot:spring-boot-starter-data-redis" }
mybatis-plus-spring-boot3-starter = { module = "com.baomidou:mybatis-plus-spring-boot3-starter", version.ref = "mybatis-plus" }
redisson-spring-boot-starter = { module = "org.redisson:redisson-spring-boot-starter", version.ref = "redisson" }
[bundles]
web = ["spring-boot-starter-web", "spring-boot-starter-data-redis"]
db = ["mybatis-plus-spring-boot3-starter", "redisson-spring-boot-starter"]
子项目引用时,一行搞定:
// user-service/build.gradle.kts
dependencies {
implementation(libs.bundles.web)
implementation(libs.bundles.db)
implementation(project(":common:common-core"))
}
我曾经见过一个项目,依赖版本散落在十几个 build.gradle 里,升级一次 Spring Boot 要改半天。用了版本目录后,改一个地方全项目生效。嗯,这才是现代化构建该有的样子。
CI/CD 流水线:自动化到底
流水线我一般分四段:代码检查 → 构建测试 → 镜像打包 → 部署发布。下面是一个 GitHub Actions 的示例:
# .github/workflows/ci-cd.yml
name: CI/CD Pipeline
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
quality:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'temurin'
- name: Code Quality Check
run: ./gradlew checkstyleMain spotbugsMain
build:
needs: quality
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build and Test
run: ./gradlew build
- name: Upload Test Reports
uses: actions/upload-artifact@v4
with:
name: test-reports
path: '**/build/reports/tests/'
docker:
needs: build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build Docker Images
run: |
./gradlew jibDockerBuild \
-Djib.to.image=registry.example.com/user-service \
-Djib.to.tags=${{ github.sha }}
- name: Push to Registry
run: docker push registry.example.com/user-service:${{ github.sha }}
deploy:
needs: docker
runs-on: ubuntu-latest
steps:
- name: Deploy to Kubernetes
run: |
kubectl set image deployment/user-service \
user-service=registry.example.com/user-service:${{ github.sha }}
quality 阶段。代码检查不过就直接 fail,别等到部署了才发现问题。我曾经有一次跳过检查直接部署,结果线上跑了一个空指针异常,查了半天发现是某个工具类没判空。
性能调优总结:让构建飞起来
最后聊聊性能。一个微服务项目,模块多、依赖多,构建慢是常态。我总结了几条实战经验:
| 优化项 | 做法 | 效果 |
|---|---|---|
| 并行构建 | org.gradle.parallel=true |
多模块并行编译,速度提升 40%-60% |
| 构建缓存 | org.gradle.caching=true |
本地缓存 + 远程缓存,增量构建秒级完成 |
| 守护进程 | org.gradle.daemon=true |
避免每次构建都启动 JVM,节省 5-10 秒 |
| 配置缓存 | org.gradle.configuration-cache=true |
缓存构建配置,减少配置阶段耗时 |
| 依赖分析 | 使用 buildScan 分析依赖耗时 |
找出慢依赖,针对性优化 |
这些配置写在 gradle.properties 里就行:
# gradle.properties
org.gradle.parallel=true
org.gradle.caching=true
org.gradle.daemon=true
org.gradle.configuration-cache=true
org.gradle.jvmargs=-Xmx2048m -XX:MaxMetaspaceSize=512m
知识体系总览
下面这张图,是我对本章内容的一个梳理。你可以把它当作一个检查清单,看看自己掌握了多少。
说实话,这一章的内容,是我这些年做微服务项目积累下来的精华。从项目结构怎么分,到构建脚本怎么写,再到流水线怎么搭,最后到性能怎么调——每一步都有坑,每一步也都有解法。
你可能会问:这些配置一次就能搞定吗?当然不是。我自己的项目也是迭代了三四版才稳定下来。但方向对了,剩下的就是时间问题。
好了,三十章的内容,到这里就全部结束了。希望这些实战经验能帮你少走弯路。如果你在项目中遇到什么问题,欢迎随时交流。
公众号:蓝海资料掘金营,微信deep3321