背景

本文是《Java 后端从小白到大神》修仙系列之框架学习,Spring Cloud 微服务实战系列的 第十二篇。Spring Cloud 是构建微服务架构的基石,拥有完整的服务治理生态,在云原生架构中广泛应用。本系列将从架构认知到实际工程,逐步构建一套企业级 Spring Cloud 微服务项目。若想详细学习请点击首篇博文开始,现在开始学习。

文章概览

Spring Cloud 架构设计模式与企业实战落地:

  1. 微服务之间调用的分层与解耦策略(API模块)
  2. 服务拆分与聚合:以业务为中心 vs 技术为中心
  3. 技术架构演进:从单体到 Serverless + 云原生趋势
  4. 统一平台中台建设思路:用户中心 / 权限中心 / 日志中心
  5. 架构师必备思维:稳定性设计 + 可观测性 + 扩展性

1. 服务间通信的分层与解耦(API模块)

1.1 原因:防止模块强耦合

微服务之间调用若使用实体类、DTO、异常等直接依赖对方模块,容易造成:

  • 模块耦合紧密,难以演化
  • 修改 A 服务的类,B/C/D 服务编译报错
  • 版本升级带来风险

1.2 解决方案:引入独立 api 模块

我们在前面的项目结构中采用如下分层策略:

1
2
3
user-api      // 提供 DTO / Feign 接口
user-service  // 实现具体业务逻辑
task-service  // 引用 user-api 发起调用

1.3 落地代码示例

user-api 模块

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
@Data
public class UserDTO {
    private Long id;
    private String username;
}

@FeignClient(name = "user-service", contextId = "userClient")
public interface UserClient {
    @GetMapping("/users/{id}")
    UserDTO getById(@PathVariable Long id);
}

task-service 模块引用

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
@RequiredArgsConstructor
@Service
public class TaskService {
    private final UserClient userClient;

    public void assignTask(Long userId) {
        UserDTO user = userClient.getById(userId);
        // ...
    }
}

实现了接口隔离 + 编译时解耦

2. 服务拆分与聚合:以业务为中心 vs 技术为中心

2.1 错误拆分方式:按技术层拆分

如下方式是常见误区:

  • auth-service:认证服务
  • user-service:用户服务
  • role-service:角色服务
  • permission-service:权限服务

这样拆分导致每个业务需要多服务协同,请求链冗长、性能下降。

2.2 推荐拆分方式:按业务域拆分

将服务围绕真实业务领域拆分,例如:

  • account-service:账户域(用户/权限/认证)
  • task-service:任务域(任务分配/流程管理)
  • report-service:报表域(数据统计/导出)

每个领域服务内部可以包含多个模块,但对外只暴露 API。

2.3 聚合场景:网关 + 聚合服务 + BFF 层

前端访问聚合数据时避免多次调用:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
@RestController
@RequiredArgsConstructor
public class DashboardController {
    private final TaskClient taskClient;
    private final UserClient userClient;

    @GetMapping("/dashboard")
    public DashboardVO get() {
        List<TaskDTO> tasks = taskClient.getRecentTasks();
        List<UserDTO> users = userClient.getTopUsers();
        return new DashboardVO(tasks, users);
    }
}

聚合由 BFF(Backend For Frontend)服务 完成,保持服务粒度。

3. 技术架构演进:从单体到 Serverless + 云原生趋势

3.1 演进阶段

阶段 特点 工具
单体应用 所有功能部署在一个进程 Spring Boot
微服务化 拆分为多个独立服务 Spring Cloud / Dubbo
容器化部署 服务容器编排 + 弹性伸缩 Docker + K8s
云原生架构 无状态、可观测、自动运维 Spring Cloud + Istio
Serverless 化 无需关注服务器 AWS Lambda / 阿里函数计算

3.2 Spring Cloud 如何适配

  • 与 Kubernetes(K8s)无缝集成:服务注册 + ConfigMap + Deployment
  • 支持 Prometheus + Grafana 可观测体系
  • 结合 Knative 支持函数式服务

构建一套可伸缩、自修复、自治的服务架构。

4. 统一平台中台建设思路:用户中心 / 权限中心 / 日志中心

企业级系统发展到中后期,通常会沉淀一套共享平台能力,构建 中台架构

4.1 用户中心(统一认证)

目标:

  • 单点登录(SSO)
  • OAuth2 / JWT 鉴权
  • 用户信息跨服务共享

使用方案:

  • Spring Authorization Server(或使用 Auth0、Keycloak)
  • 自定义认证中心服务 auth-service

4.2 权限中心(RBAC 权限体系)

提供统一的权限模型:

1
用户 -> 角色 -> 权限 -> 资源(URI/菜单/按钮)

服务调用时,网关鉴权 + 服务内权限控制:

1
2
3
@PreAuthorize("hasAuthority('task:edit')")
@PostMapping("/task")
public void updateTask(...) {}

4.3 日志中心(统一日志采集)

使用 ELK/EFK 架构:

  • Logstash / Fluentd 采集容器日志
  • Elasticsearch 存储
  • Kibana 分析搜索

统一日志格式设计(参考 starter-task-common 中封装的切面):

1
2
3
4
5
6
7
8
{
  "timestamp": "...",
  "traceId": "...",
  "service": "task-service",
  "user": "admin",
  "action": "createTask",
  "result": "success"
}

5. 架构师必备思维:稳定性设计 + 可观测性 + 扩展性

5.1 稳定性设计:三板斧

  1. 限流:Sentinel、Gateway 过滤器
  2. 熔断:Feign + Sentinel fallback 机制
  3. 降级兜底:返回缓存或兜底数据,保证系统可用

代码示例(Sentinel):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
@FeignClient(name = "user-service", fallback = UserFallback.class)
public interface UserClient {
    @GetMapping("/users/{id}")
    UserDTO getById(@PathVariable Long id);
}

@Component
public class UserFallback implements UserClient {
    public UserDTO getById(Long id) {
        return new UserDTO(id, "匿名用户");
    }
}

5.2 可观测性设计:三大支柱

类型 工具 示例
日志 ELK / Loki 请求日志、异常堆栈
指标 Prometheus CPU、内存、QPS
链路追踪 Zipkin / Skywalking 服务 A → B → C

通过统一 TraceId,实现端到端请求追踪:

1
MDC.put("traceId", UUID.randomUUID().toString());

5.3 扩展性设计:插件化 & 模块化

示例:自定义 Starter 方式封装切面日志系统 starter-task-common

1
2
3
4
5
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface TaskLog {
    String value();
}

结合 @EnableTaskLog 激活切面:

1
2
3
4
5
6
7
8
@Configuration
@ConditionalOnProperty(name = "tasklog.enabled", havingValue = "true")
public class TaskLogAutoConfig {
    @Bean
    public TaskLogAspect taskLogAspect() {
        return new TaskLogAspect();
    }
}

可插拔,符合企业架构灵活演进需求。

6. 完整项目

综合12篇所学知识,完整的项目源码、目录、架构图。

6.1 项目概述

cloudtask 是一个分布式任务管理与通知系统,用于练习 Spring Cloud 的所有组件。项目模拟企业级微服务架构,涵盖服务注册、配置管理、网关路由、服务通信、熔断降级、链路追踪、消息驱动、安全认证、分布式事务、分布式锁、API 文档和服务网格。以下是完整源码和配置文件。包含以下模块:

  • auth-service: JWT 认证和权限管理。
  • user-service: 用户数据管理,集成 Nacos 配置。
  • task-service: 任务分配,集成 Redisson 锁和链路追踪。
  • gateway-service: 网关路由和 OAuth2 认证。
  • common: 全局异常处理和工具类。
  • user-api: Feign 接口定义。
  • starter-task-common: 自定义 Starter(日志切面和注解)。
  • config-service: 动态配置管理(Nacos)。
  • tracing-service: 链路追踪(Sleuth + Zipkin)。
  • monitor-service: 监控指标(Micrometer + Prometheus + Grafana)。
  • transaction-service: 分布式事务(Seata)。
  • lock-service: 分布式锁和缓存(Redisson + Caffeine)。
  • api-doc-service: API 文档(Springdoc)。
  • mesh-service: 模拟服务网格(Istio)。
  • notify-service: 消息通知(Kafka + Spring Cloud Stream)。

6.2 架构图

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
[Client] --> [gateway-service] --> [auth-service] --> [JWT Token]
                   |                  |
                   |                  --> [user-service] --> [User Data]
                   |                  |
                   --> [task-service] --> [lock-service] --> [Redisson Lock]
                   |                  |                  |
                   |                  --> [transaction-service] --> [Seata]
                   |                  |
                   --> [notify-service] --> [Kafka] --> [Async Notification]
                   |                  |
                   --> [tracing-service] --> [Zipkin]
                   |                  |
                   --> [monitor-service] --> [Prometheus/Grafana]
                   |                  |
                   --> [config-service] --> [Nacos Config]
                   |                  |
                   --> [api-doc-service] --> [Swagger UI]
                   |
                   --> [mesh-service] --> [Istio Traffic]

6.3 项目源码

父项目pom.xml
 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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.yutao</groupId>
    <artifactId>cloudtask</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>
    <modules>
        <module>auth-service</module>
        <module>user-service</module>
        <module>task-service</module>
        <module>gateway-service</module>
        <module>common</module>
        <module>user-api</module>
        <module>starter-task-common</module>
        <module>config-service</module>
        <module>tracing-service</module>
        <module>monitor-service</module>
        <module>transaction-service</module>
        <module>lock-service</module>
        <module>api-doc-service</module>
        <module>mesh-service</module>
        <module>notify-service</module>
    </modules>

    <properties>
        <java.version>21</java.version>
        <spring.boot.version>3.2.5</spring.boot.version>
        <spring.cloud.version>2023.0.0</spring.cloud.version>
        <spring.cloud.alibaba.version>2023.0.3.3</spring.cloud.alibaba.version>
        <maven.compiler.release>${java.version}</maven.compiler.release>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring.boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring.cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${spring.cloud.alibaba.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.11.0</version>
                <configuration>
                    <release>${java.version}</release>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>
1. auth-service 项目源码

功能

  • 提供 JWT 认证和权限管理。
  • 支持用户登录,生成 JWT Token。

pom.xml

 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
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.yutao</groupId>
        <artifactId>cloudtask</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <artifactId>auth-service</artifactId>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-oauth2-authorization-server</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <dependency>
            <groupId>com.yutao</groupId>
            <artifactId>common</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>
</project>

src/main/java/com/yutao/auth/AuthServiceApp.java

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
package com.yutao.auth;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@SpringBootApplication
@EnableDiscoveryClient
public class AuthServiceApp {
    public static void main(String[] args) {
        SpringApplication.run(AuthServiceApp.class, args);
    }
}

src/main/java/com/yutao/auth/config/SecurityConfig.java

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
package com.yutao.auth.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
public class SecurityConfig {
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests(authorize -> authorize
                .requestMatchers("/auth/login").permitAll()
                .anyRequest().authenticated()
            )
            .oauth2ResourceServer(oauth2 -> oauth2.jwt());
        return http.build();
    }
}

src/main/java/com/yutao/auth/controller/AuthController.java

 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
package com.yutao.auth.controller;

import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/auth")
public class AuthController {
    @PostMapping("/login")
    public String login(@RequestBody LoginRequest request) {
        // 模拟 JWT 登录
        return "JWT Token for " + request.getUsername();
    }

    static class LoginRequest {
        private String username;
        private String password;

        public String getUsername() {
            return username;
        }

        public void setUsername(String username) {
            this.username = username;
        }

        public String getPassword() {
            return password;
        }

        public void setPassword(String password) {
            this.password = password;
        }
    }
}

src/main/resources/bootstrap.yml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
spring:
  application:
    name: auth-service
  cloud:
    nacos:
      config:
        server-addr: 127.0.0.1:8848
        file-extension: yaml
        namespace: public
        group: DEFAULT_GROUP
      discovery:
        server-addr: 127.0.0.1:8848
        namespace: public

src/main/resources/application.yml

1
2
3
4
5
6
7
8
9
server:
  port: 9001

spring:
  security:
    oauth2:
      resourceserver:
        jwt:
          issuer-uri: http://localhost:9001

Dockerfile

1
2
3
4
FROM openjdk:21-jdk-slim
WORKDIR /app
COPY target/auth-service-1.0-SNAPSHOT.jar app.jar
ENTRYPOINT ["java", "-jar", "app.jar"]
2. user-service 项目源码

功能

  • 管理用户数据(CRUD)。
  • 集成 Nacos 配置,动态加载用户设置。

pom.xml

 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
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.yutao</groupId>
        <artifactId>cloudtask</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <artifactId>user-service</artifactId>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>com.yutao</groupId>
            <artifactId>common</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>
</project>

src/main/java/com/yutao/user/UserServiceApp.java

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
package com.yutao.user;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@SpringBootApplication
@EnableDiscoveryClient
public class UserServiceApp {
    public static void main(String[] args) {
        SpringApplication.run(UserServiceApp.class, args);
    }
}

src/main/java/com/yutao/user/controller/UserController.java

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package com.yutao.user.controller;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/users")
public class UserController {
    @Value("${user.setting:default}")
    private String setting;

    @GetMapping("/setting")
    public String getSetting() {
        return setting;
    }

    @GetMapping("/{id}")
    public String getUser(@PathVariable Long id) {
        return "User: " + id;
    }
}

src/main/resources/bootstrap.yml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
spring:
  application:
    name: user-service
  profiles:
    active: dev
  cloud:
    nacos:
      config:
        server-addr: 127.0.0.1:8848
        file-extension: yaml
        namespace: public
        group: DEFAULT_GROUP
      discovery:
        server-addr: 127.0.0.1:8848
        namespace: public

src/main/resources/application.yml

1
2
3
4
5
6
7
8
server:
  port: 9002

management:
  endpoints:
    web:
      exposure:
        include: "*"

Dockerfile

1
2
3
4
FROM openjdk:21-jdk-slim
WORKDIR /app
COPY target/user-service-1.0-SNAPSHOT.jar app.jar
ENTRYPOINT ["java", "-jar", "app.jar"]
3. task-service 项目源码

功能

  • 处理任务分配,使用 Redisson 分布式锁。
  • 集成链路追踪(Sleuth)。

pom.xml

 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
41
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.yutao</groupId>
        <artifactId>cloudtask</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <artifactId>task-service</artifactId>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-sleuth</artifactId>
        </dependency>
        <dependency>
            <groupId>org.redisson</groupId>
            <artifactId>redisson-spring-boot-starter</artifactId>
            <version>3.23.0</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <dependency>
            <groupId>com.yutao</groupId>
            <artifactId>user-api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>com.yutao</groupId>
            <artifactId>common</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>
</project>

src/main/java/com/yutao/task/TaskServiceApp.java

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
package com.yutao.task;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;

@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class TaskServiceApp {
    public static void main(String[] args) {
        SpringApplication.run(TaskServiceApp.class, args);
    }
}

src/main/java/com/yutao/task/controller/TaskController.java

 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
package com.yutao.task.controller;

import com.yutao.user.api.UserClient;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/tasks")
public class TaskController {
    @Autowired
    private RedissonClient redissonClient;
    @Autowired
    private UserClient userClient;

    @GetMapping("/assign")
    public String assignTask() {
        RLock lock = redissonClient.getLock("task-lock");
        try {
            if (lock.tryLock()) {
                String user = userClient.getUser(1L);
                return "Task assigned to " + user;
            }
            return "Task assignment locked";
        } finally {
            lock.unlock();
        }
    }
}

src/main/resources/bootstrap.yml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
spring:
  application:
    name: task-service
  cloud:
    nacos:
      config:
        server-addr: 127.0.0.1:8848
        file-extension: yaml
        namespace: public
        group: DEFAULT_GROUP
      discovery:
        server-addr: 127.0.0.1:8848
        namespace: public

src/main/resources/application.yml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
server:
  port: 9003

spring:
  sleuth:
    sampler:
      probability: 1.0
  redis:
    host: localhost
    port: 6379

Dockerfile

1
2
3
4
FROM openjdk:21-jdk-slim
WORKDIR /app
COPY target/task-service-1.0-SNAPSHOT.jar app.jar
ENTRYPOINT ["java", "-jar", "app.jar"]
4. gateway-service 项目源码

功能

  • 提供网关路由和 OAuth2 认证。
  • 统一入口,路由到各服务。

pom.xml

 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
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.yutao</groupId>
        <artifactId>cloudtask</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <artifactId>gateway-service</artifactId>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-oauth2-resource-server</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <dependency>
            <groupId>com.yutao</groupId>
            <artifactId>common</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>
</project>

src/main/java/com/yutao/gateway/GatewayServiceApp.java

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
package com.yutao.gateway;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@SpringBootApplication
@EnableDiscoveryClient
public class GatewayServiceApp {
    public static void main(String[] args) {
        SpringApplication.run(GatewayServiceApp.class, args);
    }
}

src/main/java/com/yutao/gateway/config/GatewayConfig.java

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
package com.yutao.gateway.config;

import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class GatewayConfig {
    @Bean
    public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
        return builder.routes()
                .route("auth_service", r -> r.path("/auth/**")
                        .uri("lb://auth-service"))
                .route("user_service", r -> r.path("/users/**")
                        .uri("lb://user-service"))
                .route("task_service", r -> r.path("/tasks/**")
                        .uri("lb://task-service"))
                .build();
    }
}

src/main/java/com/yutao/gateway/config/SecurityConfig.java

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.yutao.gateway.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.web.server.SecurityWebFilterChain;

@Configuration
@EnableWebFluxSecurity
public class SecurityConfig {
    @Bean
    public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
        http
            .authorizeExchange(exchanges -> exchanges
                .pathMatchers("/auth/**").permitAll()
                .anyExchange().authenticated()
            )
            .oauth2ResourceServer(oauth2 -> oauth2.jwt());
        return http.build();
    }
}

src/main/resources/bootstrap.yml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
spring:
  application:
    name: gateway-service
  cloud:
    nacos:
      config:
        server-addr: 127.0.0.1:8848
        file-extension: yaml
        namespace: public
        group: DEFAULT_GROUP
      discovery:
        server-addr: 127.0.0.1:8848
        namespace: public

src/main/resources/application.yml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
server:
  port: 8888

spring:
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true
          lower-case-service-id: true

Dockerfile

1
2
3
4
FROM openjdk:21-jdk-slim
WORKDIR /app
COPY target/gateway-service-1.0-SNAPSHOT.jar app.jar
ENTRYPOINT ["java", "-jar", "app.jar"]
5. common 项目源码

功能

  • 提供全局异常处理和工具类。

pom.xml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.yutao</groupId>
        <artifactId>cloudtask</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <artifactId>common</artifactId>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
        </dependency>
    </dependencies>
</project>

src/main/java/com/yutao/common/exception/GlobalExceptionHandler.java

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
package com.yutao.common.exception;

import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

@RestControllerAdvice
public class GlobalExceptionHandler {
    @ExceptionHandler(Exception.class)
    public String handleException(Exception e) {
        return "Error: " + e.getMessage();
    }
}

src/main/java/com/yutao/common/util/JsonUtil.java

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
package com.yutao.common.util;

import com.fasterxml.jackson.databind.ObjectMapper;

public class JsonUtil {
    private static final ObjectMapper mapper = new ObjectMapper();

    public static String toJson(Object obj) throws Exception {
        return mapper.writeValueAsString(obj);
    }
}
6. user-api 项目源码

功能

  • 定义 Feign 接口,供其他服务调用。

pom.xml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.yutao</groupId>
        <artifactId>cloudtask</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <artifactId>user-api</artifactId>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
    </dependencies>
</project>

src/main/java/com/yutao/user/api/UserClient.java

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
package com.yutao.user.api;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

@FeignClient(name = "user-service")
public interface UserClient {
    @GetMapping("/users/{id}")
    String getUser(@PathVariable("id") Long id);
}
7. starter-task-common 项目源码

功能

  • 提供自定义 Starter,包含日志切面和注解,用于在其他模块中启用日志记录功能。

pom.xml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="[invalid url, do not cite] xmlns:xsi="[invalid url, do not cite]
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 [invalid url, do not cite]
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.yutao</groupId>
        <artifactId>cloudtask</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <artifactId>starter-task-common</artifactId>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>
    </dependencies>
</project>

src/main/java/com/yutao/starter/aspect/TaskAspect.java

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package com.yutao.starter.aspect;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class TaskAspect {
    private static final Logger logger = LoggerFactory.getLogger(TaskAspect.class);

    @Around("@annotation(com.yutao.starter.annotation.TaskLog)")
    public Object logTask(ProceedingJoinPoint joinPoint) throws Throwable {
        String methodName = joinPoint.getSignature().getName();
        logger.info("Starting task: {}", methodName);
        Object result = joinPoint.proceed();
        logger.info("Completed task: {}", methodName);
        return result;
    }
}

src/main/java/com/yutao/starter/annotation/TaskLog.java

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
package com.yutao.starter.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface TaskLog {
}

src/main/java/com/yutao/starter/TaskCommonAutoConfiguration.java

1
2
3
4
5
6
7
8
9
package com.yutao.starter;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan("com.yutao.starter.aspect")
public class TaskCommonAutoConfiguration {
}
8. config-service 项目源码

功能

  • 使用 Nacos Config 管理动态配置,支持多环境(dev/test/prod)。

pom.xml

 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
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="[invalid url, do not cite] xmlns:xsi="[invalid url, do not cite]
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 [invalid url, do not cite]
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.yutao</groupId>
        <artifactId>cloudtask</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <artifactId>config-service</artifactId>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>com.yutao</groupId>
            <artifactId>common</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>
</project>

src/main/java/com/yutao/config/ConfigServiceApp.java

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
package com.yutao.config;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@SpringBootApplication
@EnableDiscoveryClient
public class ConfigServiceApp {
    public static void main(String[] args) {
        SpringApplication.run(ConfigServiceApp.class, args);
    }
}

src/main/java/com/yutao/config/controller/ConfigController.java

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
package com.yutao.config.controller;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/config")
@RefreshScope
public class ConfigController {
    @Value("${config.title:默认配置}")
    private String title;

    @GetMapping("/title")
    public String getTitle() {
        return title;
    }
}

src/main/resources/bootstrap.yml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
spring:
  application:
    name: config-service
  profiles:
    active: dev
  cloud:
    nacos:
      config:
        server-addr: 127.0.0.1:8848
        file-extension: yaml
        namespace: public
        group: DEFAULT_GROUP
      discovery:
        server-addr: 127.0.0.1:8848
        namespace: public

src/main/resources/application.yml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
server:
  port: 8889

management:
  endpoints:
    web:
      exposure:
        include: "*"
  endpoint:
    refresh:
      enabled: true

logging:
  level:
    com.alibaba.nacos: DEBUG

Dockerfile

1
2
3
4
FROM openjdk:21-jdk-slim
WORKDIR /app
COPY target/config-service-1.0-SNAPSHOT.jar app.jar
ENTRYPOINT ["java", "-jar", "app.jar"]

Nacos 配置 (config-service-dev.yaml)

在 Nacos 控制台中创建,命名空间为 public,分组为 DEFAULT_GROUP

1
2
config:
  title: "Spring Cloud 微服务配置中心空间启动成功"
9. tracing-service 项目源码

功能

  • 使用 Sleuth 和 Zipkin 实现分布式链路追踪,记录服务调用链。

pom.xml

 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
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="[invalid url, do not cite] xmlns:xsi="[invalid url, do not cite]
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 [invalid url, do not cite]
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.yutao</groupId>
        <artifactId>cloudtask</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <artifactId>tracing-service</artifactId>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-sleuth</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zipkin</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <dependency>
            <groupId>com.yutao</groupId>
            <artifactId>common</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>
</project>

src/main/java/com/yutao/tracing/TracingServiceApp.java

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
package com.yutao.tracing;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@SpringBootApplication
@EnableDiscoveryClient
public class TracingServiceApp {
    public static void main(String[] args) {
        SpringApplication.run(TracingServiceApp.class, args);
    }
}

src/main/java/com/yutao/tracing/controller/TraceController.java

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
package com.yutao.tracing.controller;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/trace")
public class TraceController {
    private static final Logger logger = LoggerFactory.getLogger(TraceController.class);

    @GetMapping("/test")
    public String testTrace() {
        logger.info("Trace test endpoint called");
        return "Trace test completed";
    }
}

src/main/resources/bootstrap.yml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
spring:
  application:
    name: tracing-service
  cloud:
    nacos:
      config:
        server-addr: 127.0.0.1:8848
        file-extension: yaml
        namespace: public
        group: DEFAULT_GROUP
      discovery:
        server-addr: 127.0.0.1:8848
        namespace: public

src/main/resources/application.yml

1
2
3
4
5
6
7
8
9
server:
  port: 9411

spring:
  sleuth:
    sampler:
      probability: 1.0
  zipkin:
    base-url: [invalid url, do not cite]

Dockerfile

1
2
3
4
FROM openjdk:21-jdk-slim
WORKDIR /app
COPY target/tracing-service-1.0-SNAPSHOT.jar app.jar
ENTRYPOINT ["java", "-jar", "app.jar"]
10. monitor-service 项目源码

功能

  • 使用 Micrometer 和 Prometheus 收集监控指标,结合 Grafana 可视化。

pom.xml

 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
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="[invalid url, do not cite] xmlns:xsi="[invalid url, do not cite]
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 [invalid url, do not cite]
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.yutao</groupId>
        <artifactId>cloudtask</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <artifactId>monitor-service</artifactId>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>io.micrometer</groupId>
            <artifactId>micrometer-registry-prometheus</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <dependency>
            <groupId>com.yutao</groupId>
            <artifactId>common</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>
</project>

src/main/java/com/yutao/monitor/MonitorServiceApp.java

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
package com.yutao.monitor;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@SpringBootApplication
@EnableDiscoveryClient
public class MonitorServiceApp {
    public static void main(String[] args) {
        SpringApplication.run(MonitorServiceApp.class, args);
    }
}

src/main/java/com/yutao/monitor/controller/MonitorController.java

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
package com.yutao.monitor.controller;

import io.micrometer.core.instrument.MeterRegistry;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/monitor")
public class MonitorController {
    @Autowired
    private MeterRegistry meterRegistry;

    @GetMapping("/metrics")
    public String getMetrics() {
        meterRegistry.counter("custom.metrics", "type", "test").increment();
        return "Metrics recorded";
    }
}

src/main/resources/bootstrap.yml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
spring:
  application:
    name: monitor-service
  cloud:
    nacos:
      config:
        server-addr: 127.0.0.1:8848
        file-extension: yaml
        namespace: public
        group: DEFAULT_GROUP
      discovery:
        server-addr: 127.0.0.1:8848
        namespace: public

src/main/resources/application.yml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
server:
  port: 9090

management:
  endpoints:
    web:
      exposure:
        include: "*"
  metrics:
    export:
      prometheus:
        enabled: true

Dockerfile

1
2
3
4
FROM openjdk:21-jdk-slim
WORKDIR /app
COPY target/monitor-service-1.0-SNAPSHOT.jar app.jar
ENTRYPOINT ["java", "-jar", "app.jar"]
11. transaction-service 项目源码

功能

  • 使用 Seata 实现分布式事务管理,确保跨服务数据一致性。

pom.xml

 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
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="[invalid url, do not cite] xmlns:xsi="[invalid url, do not cite]
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 [invalid url, do not cite]
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.yutao</groupId>
        <artifactId>cloudtask</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <artifactId>transaction-service</artifactId>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <dependency>
            <groupId>com.yutao</groupId>
            <artifactId>common</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>
</project>

src/main/java/com/yutao/transaction/TransactionServiceApp.java

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
package com.yutao.transaction;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@SpringBootApplication
@EnableDiscoveryClient
public class TransactionServiceApp {
    public static void main(String[] args) {
        SpringApplication.run(TransactionServiceApp.class, args);
    }
}

src/main/java/com/yutao/transaction/controller/TransactionController.java

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
package com.yutao.transaction.controller;

import io.seata.spring.annotation.GlobalTransactional;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/transaction")
public class TransactionController {
    @GlobalTransactional
    @GetMapping("/execute")
    public String executeTransaction() {
        // 模拟分布式事务
        return "Transaction executed";
    }
}

src/main/resources/bootstrap.yml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
spring:
  application:
    name: transaction-service
  cloud:
    nacos:
      config:
        server-addr: 127.0.0.1:8848
        file-extension: yaml
        namespace: public
        group: DEFAULT_GROUP
      discovery:
        server-addr: 127.0.0.1:8848
        namespace: public

src/main/resources/application.yml

 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
server:
  port: 8091

seata:
  enabled: true
  application-id: ${spring.application.name}
  tx-service-group: my_tx_group
  enable-auto-data-source-proxy: true
  use-jdk-proxy: false
  service:
    vgroup-mapping:
      my_tx_group: default
  registry:
    type: nacos
    nacos:
      application: seata-server
      server-addr: 127.0.0.1:8848
      group: SEATA_GROUP
      namespace: public
  config:
    type: nacos
    nacos:
      server-addr: 127.0.0.1:8848
      group: SEATA_GROUP
      namespace: public

Dockerfile

1
2
3
4
FROM openjdk:21-jdk-slim
WORKDIR /app
COPY target/transaction-service-1.0-SNAPSHOT.jar app.jar
ENTRYPOINT ["java", "-jar", "app.jar"]
12. lock-service 项目源码

功能

  • 使用 Redisson 实现分布式锁,Caffeine 实现本地缓存,防止并发冲突和优化性能。

pom.xml

 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
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="[invalid url, do not cite] xmlns:xsi="[invalid url, do not cite]
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 [invalid url, do not cite]
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.yutao</groupId>
        <artifactId>cloudtask</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <artifactId>lock-service</artifactId>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.redisson</groupId>
            <artifactId>redisson-spring-boot-starter</artifactId>
            <version>3.23.0</version>
        </dependency>
        <dependency>
            <groupId>com.github.ben-manes.caffeine</groupId>
            <artifactId>caffeine</artifactId>
            <version>3.1.8</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <dependency>
            <groupId>com.yutao</groupId>
            <artifactId>common</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>
</project>

src/main/java/com/yutao/lock/LockServiceApp.java

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
package com.yutao.lock;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@SpringBootApplication
@EnableDiscoveryClient
public class LockServiceApp {
    public static void main(String[] args) {
        SpringApplication.run(LockServiceApp.class, args);
    }
}

src/main/java/com/yutao/lock/controller/LockController.java

 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
package com.yutao.lock.controller;

import com.github.benmanes.caffeine.cache.Cache;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/lock")
public class LockController {
    @Autowired
    private RedissonClient redissonClient;
    @Autowired
    private Cache<String, String> caffeineCache;

    @GetMapping("/acquire")
    public String acquireLock() {
        RLock lock = redissonClient.getLock("resource-lock");
        try {
            if (lock.tryLock()) {
                String cachedValue = caffeineCache.getIfPresent("key");
                if (cachedValue == null) {
                    cachedValue = "Cached Value";
                    caffeineCache.put("key", cachedValue);
                }
                return "Lock acquired, cache: " + cachedValue;
            }
            return "Lock acquisition failed";
        } finally {
            lock.unlock();
        }
    }
}

src/main/java/com/yutao/lock/config/CacheConfig.java

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
package com.yutao.lock.config;

import com.github.benmanes.caffeine.cache.Caffeine;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class CacheConfig {
    @Bean
    public com.github.benmanes.caffeine.cache.Cache<String, String> caffeineCache() {
        return Caffeine.newBuilder()
                .maximumSize(1000)
                .build();
    }
}

src/main/resources/bootstrap.yml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
spring:
  application:
    name: lock-service
  cloud:
    nacos:
      config:
        server-addr: 127.0.0.1:8848
        file-extension: yaml
        namespace: public
        group: DEFAULT_GROUP
      discovery:
        server-addr: 127.0.0.1:8848
        namespace: public

src/main/resources/application.yml

1
2
3
4
5
6
7
server:
  port: 8092

spring:
  redis:
    host: localhost
    port: 6379

Dockerfile

1
2
3
4
FROM openjdk:21-jdk-slim
WORKDIR /app
COPY target/lock-service-1.0-SNAPSHOT.jar app.jar
ENTRYPOINT ["java", "-jar", "app.jar"]
13. api-doc-service 项目源码

功能

  • 使用 Springdoc 生成 API 文档,支持 Swagger UI。

  • 提供 RESTful API 的可视化接口,方便开发和测试。

pom.xml

 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
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.yutao</groupId>
        <artifactId>cloudtask</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <artifactId>api-doc-service</artifactId>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springdoc</groupId>
            <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
            <version>2.0.2</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <dependency>
            <groupId>com.yutao</groupId>
            <artifactId>common</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>
</project>

src/main/java/com/yutao/apidoc/ApiDocServiceApp.java

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
package com.yutao.apidoc;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@SpringBootApplication
@EnableDiscoveryClient
public class ApiDocServiceApp {
    public static void main(String[] args) {
        SpringApplication.run(ApiDocServiceApp.class, args);
    }
}

src/main/java/com/yutao/apidoc/controller/ApiDocController.java

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
package com.yutao.apidoc.controller;

import io.swagger.v3.oas.annotations.Operation;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api-docs")
public class ApiDocController {
    @Operation(summary = "测试 API 文档")
    @GetMapping("/test")
    public String testApi() {
        return "API 文档测试";
    }
}

src/main/resources/bootstrap.yml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
spring:
  application:
    name: api-doc-service
  cloud:
    nacos:
      config:
        server-addr: 127.0.0.1:8848
        file-extension: yaml
        namespace: public
        group: DEFAULT_GROUP
      discovery:
        server-addr: 127.0.0.1:8848
        namespace: public

src/main/resources/application.yml

1
2
3
4
5
6
server:
  port: 8081

springdoc:
  swagger-ui:
    path: /swagger-ui.html

Dockerfile

1
2
3
4
FROM openjdk:21-jdk-slim
WORKDIR /app
COPY target/api-doc-service-1.0-SNAPSHOT.jar app.jar
ENTRYPOINT ["java", "-jar", "app.jar"]

使用说明

  • 访问 `[invalid url, do not cite] 查看 Swagger UI。

  • 确保 Nacos 服务运行并注册。

14. mesh-service 项目源码

功能

  • 模拟服务网格(Istio),实现流量管理和故障注入。

  • 提供简单的 REST 接口,模拟服务网格环境。

pom.xml

 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
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.yutao</groupId>
        <artifactId>cloudtask</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <artifactId>mesh-service</artifactId>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <dependency>
            <groupId>com.yutao</groupId>
            <artifactId>common</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>
</project>

src/main/java/com/yutao/mesh/MeshServiceApp.java

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
package com.yutao.mesh;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@SpringBootApplication
@EnableDiscoveryClient
public class MeshServiceApp {
    public static void main(String[] args) {
        SpringApplication.run(MeshServiceApp.class, args);
    }
}

src/main/java/com/yutao/mesh/controller/MeshController.java

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
package com.yutao.mesh.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/mesh")
public class MeshController {
    @GetMapping("/test")
    public String testMesh() {
        return "服务网格测试";
    }
}

src/main/resources/bootstrap.yml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
spring:
  application:
    name: mesh-service
  cloud:
    nacos:
      config:
        server-addr: 127.0.0.1:8848
        file-extension: yaml
        namespace: public
        group: DEFAULT_GROUP
      discovery:
        server-addr: 127.0.0.1:8848
        namespace: public

src/main/resources/application.yml

1
2
server:
  port: 8082

Dockerfile

1
2
3
4
FROM openjdk:21-jdk-slim
WORKDIR /app
COPY target/mesh-service-1.0-SNAPSHOT.jar app.jar
ENTRYPOINT ["java", "-jar", "app.jar"]

使用说明

  • 模拟 Istio 流量管理需部署 Istio 环境(例如 Kubernetes + Istio)。

  • 访问 `[invalid url, do not cite] 测试服务网格接口。

15. notify-service 项目源码

功能

  • 使用 Kafka 和 Spring Cloud Stream 实现异步消息通知。

  • 支持任务分配后的通知发送。

pom.xml

 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
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.yutao</groupId>
        <artifactId>cloudtask</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <artifactId>notify-service</artifactId>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-stream</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-stream-binder-kafka</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <dependency>
            <groupId>com.yutao</groupId>
            <artifactId>common</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>
</project>

src/main/java/com/yutao/notify/NotifyServiceApp.java

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
package com.yutao.notify;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.stream.annotation.EnableBinding;
import org.springframework.cloud.stream.messaging.Source;

@SpringBootApplication
@EnableDiscoveryClient
@EnableBinding(Source.class)
public class NotifyServiceApp {
    public static void main(String[] args) {
        SpringApplication.run(NotifyServiceApp.class, args);
    }
}

src/main/java/com/yutao/notify/service/NotificationService.java

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
package com.yutao.notify.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.stream.function.StreamBridge;
import org.springframework.stereotype.Service;

@Service
public class NotificationService {
    @Autowired
    private StreamBridge streamBridge;

    public void sendNotification(String message) {
        streamBridge.send("output", message);
    }
}

src/main/java/com/yutao/notify/controller/NotifyController.java

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
package com.yutao.notify.controller;

import com.yutao.notify.service.NotificationService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/notify")
public class NotifyController {
    @Autowired
    private NotificationService notificationService;

    @PostMapping("/send")
    public String sendNotification(@RequestBody String message) {
        notificationService.sendNotification(message);
        return "通知已发送";
    }
}

src/main/resources/bootstrap.yml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
spring:
  application:
    name: notify-service
  cloud:
    nacos:
      config:
        server-addr: 127.0.0.1:8848
        file-extension: yaml
        namespace: public
        group: DEFAULT_GROUP
      discovery:
        server-addr: 127.0.0.1:8848
        namespace: public

src/main/resources/application.yml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
server:
  port: 8083

spring:
  cloud:
    stream:
      bindings:
        output:
          destination: notification-topic
      kafka:
        binder:
          brokers: localhost:9092

Dockerfile

1
2
3
4
FROM openjdk:21-jdk-slim
WORKDIR /app
COPY target/notify-service-1.0-SNAPSHOT.jar app.jar
ENTRYPOINT ["java", "-jar", "app.jar"]
Docker Compose 配置

以下是 docker-compose.yml,用于编排所有服务:

  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
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
version: '3.8'
services:
  nacos:
    image: nacos/nacos-server:v2.3.0
    ports:
      - "8848:8848"
      - "9848:9848"
    environment:
      MODE: standalone
      SPRING_DATASOURCE_PLATFORM: mysql
      MYSQL_SERVICE_HOST: mysql
      MYSQL_SERVICE_PORT: 3306
      MYSQL_SERVICE_USER: root
      MYSQL_SERVICE_PASSWORD: root
      MYSQL_SERVICE_DB_NAME: nacos_config
    healthcheck:
      test: ["CMD", "curl", "-f", "[invalid url, do not cite]
      interval: 10s
      timeout: 5s
      retries: 5

  mysql:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: root
    ports:
      - "3306:3306"
    volumes:
      - /Users/yutao/Downloads/devtool/docker/mysqldata:/var/lib/mysql
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      interval: 10s
      timeout: 5s
      retries: 5

  redis:
    image: redis:7.2
    ports:
      - "6379:6379"

  kafka:
    image: confluentinc/cp-kafka:7.3.0
    ports:
      - "9092:9092"
    environment:
      KAFKA_BROKER_ID: 1
      KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
      KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:9092
      KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
    depends_on:
      - zookeeper

  zookeeper:
    image: confluentinc/cp-zookeeper:7.3.0
    ports:
      - "2181:2181"
    environment:
      ZOOKEEPER_CLIENT_PORT: 2181
      ZOOKEEPER_TICK_TIME: 2000

  auth-service:
    image: auth-service
    ports:
      - "9001:9001"
    depends_on:
      nacos:
        condition: service_healthy
    networks:
      - cloudtask-net

  user-service:
    image: user-service
    ports:
      - "9002:9002"
    depends_on:
      nacos:
        condition: service_healthy
      mysql:
        condition: service_healthy
    environment:
      - SPRING_DATASOURCE_URL=jdbc:mysql://mysql:3306/user_db?characterEncoding=utf8&connectTimeout=2000&allowPublicKeyRetrieval=true&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=Asia/Shanghai
      - SPRING_DATASOURCE_USERNAME=root
      - SPRING_DATASOURCE_PASSWORD=root
    networks:
      - cloudtask-net

  task-service:
    image: task-service
    ports:
      - "9003:9003"
    depends_on:
      nacos:
        condition: service_healthy
      redis:
        condition: service_started
    networks:
      - cloudtask-net

  gateway-service:
    image: gateway-service
    ports:
      - "8888:8888"
    depends_on:
      nacos:
        condition: service_healthy
    networks:
      - cloudtask-net

  api-doc-service:
    image: api-doc-service
    ports:
      - "8081:8081"
    depends_on:
      nacos:
        condition: service_healthy
    networks:
      - cloudtask-net

  mesh-service:
    image: mesh-service
    ports:
      - "8082:8082"
    depends_on:
      nacos:
        condition: service_healthy
    networks:
      - cloudtask-net

  notify-service:
    image: notify-service
    ports:
      - "8083:8083"
    depends_on:
      nacos:
        condition: service_healthy
      kafka:
        condition: service_started
    networks:
      - cloudtask-net

networks:
  cloudtask-net:
    driver: bridge

总结

本篇从架构设计的角度系统总结了 Spring Cloud 在企业落地过程中的 5 大关键:

  1. 服务解耦分层:避免模块耦合
  2. 服务拆分聚合:以业务为中心建模
  3. 架构演进趋势:云原生 + Serverless 是方向
  4. 统一中台建设:沉淀复用基础能力
  5. 架构三性思维:稳定性、可观测性、扩展性

要求既要做好技术选型,也要结合业务场景,才能真正做到架构师的落地修行。