实战案例:微服务多模块项目、全栈构建脚本、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
注意:配置缓存虽然快,但有些插件不兼容。启用后如果遇到奇怪的问题,先关掉试试。我遇到过几次因为配置缓存导致任务顺序错乱的情况。

知识体系总览

下面这张图,是我对本章内容的一个梳理。你可以把它当作一个检查清单,看看自己掌握了多少。

微服务多模块项目实战知识体系 Gradle 微服务实战 多模块项目结构 • 按业务领域划分模块 • common 模块轻量化 • 根项目协调,子项目决策 全栈构建脚本 • 根项目配置插件 • 子项目按需 apply • 版本目录统一管理 CI/CD 流水线 • 代码检查 → 构建测试 • 镜像打包 → 部署发布 • quality 阶段前置 性能调优总结 • 并行构建 • 构建缓存 • 配置缓存 核心理念 模块化拆分 + 自动化构建 + 持续优化 = 高效微服务交付

说实话,这一章的内容,是我这些年做微服务项目积累下来的精华。从项目结构怎么分,到构建脚本怎么写,再到流水线怎么搭,最后到性能怎么调——每一步都有坑,每一步也都有解法。

你可能会问:这些配置一次就能搞定吗?当然不是。我自己的项目也是迭代了三四版才稳定下来。但方向对了,剩下的就是时间问题。

好了,三十章的内容,到这里就全部结束了。希望这些实战经验能帮你少走弯路。如果你在项目中遇到什么问题,欢迎随时交流。

最后送你一句话:好的构建脚本,不是写出来的,是改出来的。别怕重构,别怕试错。

公众号:蓝海资料掘金营,微信deep3321