零基础学习:Spring Cloud 微服务全栈实践

零基础学习:Spring Cloud 微服务全栈实践

一、微服务与 Spring Cloud 认知

1. 微服务核心概念

  • 定义:将单体应用拆分为小型、自治的服务,每个服务聚焦单一业务能力,通过轻量级通信协议(如 HTTP/REST)协同工作。
  • 核心特性
    • 单一职责:每个服务对应特定业务领域(如用户服务、订单服务)。
    • 自治性:独立开发、测试、部署、扩缩容,不依赖其他服务的部署。
    • 松耦合:通过 API 契约通信,内部实现细节对外部透明。
    • 技术多样性:不同服务可选择适合自身的技术栈(如 Java、Go、Python)。

2. 微服务解决的问题

  • 单体应用痛点
    • 代码臃肿,维护困难;
    • 技术栈锁定,难以引入新技术;
    • 部署风险高,一个小bug可能导致整个应用崩溃;
    • 扩展性差,无法针对热点业务单独扩容。
  • 微服务优势
    • 灵活迭代:小团队可快速开发、部署新功能;
    • 独立扩容:针对高并发服务单独增加实例;
    • 容错性强:单个服务故障不影响整体系统;
    • 技术选型灵活:根据业务场景选择最优技术栈。

3. Spring Cloud 定位与价值

  • 定义:Spring Cloud 是基于 Spring Boot 的微服务开发工具集,提供了一套完整的微服务架构解决方案。
  • 核心价值
    • 简化微服务开发:封装了服务注册发现、配置中心、负载均衡、熔断降级等核心能力;
    • 开箱即用:提供了一系列 starter 组件,开发者可快速集成;
    • 生态完善:与 Spring Boot 无缝集成,支持各种主流中间件(如 Eureka、Consul、Nacos、RabbitMQ);
    • 社区活跃:持续更新迭代,解决实际开发中的问题。

4. Spring Cloud 与 Spring Boot 的关系

  • Spring Boot:专注于快速开发单个独立的 Spring 应用,提供自动配置、 starters、嵌入式服务器等特性,简化了 Spring 应用的初始搭建和开发过程。
  • Spring Cloud:基于 Spring Boot 构建,用于开发分布式系统中的微服务。它将多个 Spring Boot 应用连接起来,提供了微服务架构所需的各种功能,如服务注册与发现、配置管理、断路器、网关等。
  • 关系总结:Spring Boot 是 Spring Cloud 的基础,Spring Cloud 是 Spring Boot 在分布式系统场景下的扩展和应用。一个 Spring Cloud 微服务系统由多个 Spring Boot 应用组成,每个应用都是一个独立的微服务。

二、Spring Cloud 核心组件

1. 服务注册与发现(Eureka/Nacos)

  • 核心功能
    • 服务注册:服务启动时,将自身信息(如服务名、IP、端口)注册到注册中心;
    • 服务发现:客户端通过服务名从注册中心获取可用服务列表,实现动态调用。
  • Eureka 特性
    • 基于 AP 原则(可用性、分区容错性),适合可用性要求高的场景;
    • 自我保护机制:当注册中心丢失部分服务实例时,不会立即剔除,而是保留一段时间,避免误判;
    • 客户端缓存:客户端会缓存服务列表,即使注册中心宕机,仍可正常调用已缓存的服务。
  • Nacos 特性
    • 支持 AP 和 CP 模式切换(默认 AP),适配不同场景;
    • 除注册发现外,还提供配置中心功能,一站式解决方案;
    • 动态配置:支持配置实时更新,无需重启服务;
    • 服务健康检查:提供多种健康检查方式(如 HTTP、TCP、MySQL),确保服务可用性。

2. 配置中心(Spring Cloud Config/Nacos)

  • 核心功能
    • 集中管理配置:将分散在各个服务的配置(如数据库连接、接口地址)集中存储;
    • 动态配置更新:支持配置实时推送,服务无需重启即可生效;
    • 环境隔离:为不同环境(开发、测试、生产)提供不同配置。
  • Spring Cloud Config 特性
    • 基于 Git 存储配置,支持版本控制、回滚;
    • 客户端拉取配置:服务启动时从 Config Server 拉取配置,默认不支持实时更新(需结合 Spring Cloud Bus 实现);
    • 支持加密配置:对敏感配置(如密码)进行加密存储。
  • Nacos Config 特性
    • 支持多种存储方式(本地文件、MySQL、集群);
    • 动态更新:配置变更后,实时推送到客户端;
    • 配置监听:客户端可监听特定配置项,实现业务逻辑动态调整;
    • 支持配置导入/导出,方便批量管理。

3. 负载均衡(Ribbon/OpenFeign)

  • 核心功能
    • 客户端负载均衡:客户端从服务列表中选择一个可用服务实例进行调用,避免单点故障;
    • 支持多种负载均衡策略:如轮询、随机、权重、响应时间加权等。
  • Ribbon 特性
    • 独立的负载均衡组件,可与 RestTemplate 结合使用;
    • 支持自定义负载均衡策略:通过实现 IRule 接口扩展;
    • 服务健康检查:结合 Eureka 可实现基于服务健康状态的负载均衡(只调用健康的服务实例)。
  • OpenFeign 特性
    • 基于接口的声明式调用:通过注解定义接口,自动生成代理类,简化服务调用代码;
    • 内置 Ribbon:默认集成 Ribbon 实现负载均衡;
    • 支持请求拦截器:可在请求发送前进行拦截处理(如添加认证信息、日志记录);
    • 支持 fallback:结合 Hystrix 实现服务降级。

4. 熔断降级(Hystrix/Resilience4j)

  • 核心功能
    • 熔断:当服务调用失败率达到阈值时,自动触发熔断,停止调用该服务,避免级联故障;
    • 降级:熔断后或服务不可用时,返回预设的 fallback 结果(如默认值、缓存数据),保证系统可用性;
    • 限流:限制服务的并发请求数,避免服务因过载而崩溃。
  • Hystrix 特性
    • 基于舱壁模式:将不同服务的调用隔离在不同线程池,避免一个服务故障耗尽所有线程资源;
    • 支持熔断、降级、限流、请求缓存等多种功能;
    • 监控面板:提供 Hystrix Dashboard 可视化监控服务调用情况。
  • Resilience4j 特性
    • 轻量级:基于 Java 8 开发,无依赖,性能优于 Hystrix;
    • 模块化:将熔断、降级、限流等功能拆分为独立模块,可按需引入;
    • 支持函数式编程:通过 Lambda 表达式简化配置;
    • 监控支持:集成 Micrometer、Prometheus 等监控工具。

5. API 网关(Spring Cloud Gateway)

  • 核心功能
    • 路由转发:将客户端请求根据路径、服务名等规则转发到对应的微服务;
    • 统一入口:为所有微服务提供统一的访问入口,方便管理和监控;
    • 认证授权:对请求进行身份验证和权限校验,防止非法访问;
    • 限流熔断:对网关层面的请求进行限流,对下游服务进行熔断降级;
    • 日志监控:记录请求日志,方便排查问题。
  • 特性
    • 基于 ***ty 开发,异步非阻塞,性能高;
    • 支持 WebSocket;
    • 路由配置灵活:支持基于配置文件、数据库、动态路由等多种方式;
    • 过滤器链:提供丰富的过滤器(如请求头过滤、参数过滤、响应处理),支持自定义过滤器。

6. 服务链路追踪(Sleuth + Zipkin)

  • 核心功能
    • 追踪请求链路:记录请求从客户端到各个微服务的调用路径、耗时、状态等信息;
    • 问题排查:通过链路追踪快速定位跨服务调用中的问题(如哪个服务调用超时、报错);
    • 性能分析:分析各个服务的调用耗时,找出性能瓶颈。
  • Sleuth 特性
    • 轻量级:通过 MDC(Mapped Diagnostic Context)在日志中添加追踪信息(如 traceId、spanId);
    • 无侵入:无需修改业务代码,只需引入依赖即可;
    • 支持多种采样策略:如全采样、固定比例采样、_rate 采样等。
  • Zipkin 特性
    • 可视化界面:展示请求链路的调用关系、耗时、状态;
    • 支持多种存储方式:如内存、MySQL、Elasticsearch;
    • 服务依赖分析:展示各个服务之间的调用依赖关系;
    • 告警功能:当调用耗时超过阈值或失败率过高时,触发告警。

三、微服务项目初始化

1. 技术选型

  • 核心框架:Spring Boot 2.x、Spring Cloud Hoxton/Spring Cloud Alibaba 2021.x
  • 注册中心:Nacos(推荐,一站式解决方案)
  • 配置中心:Nacos Config
  • 负载均衡:OpenFeign(结合 Ribbon)
  • 熔断降级:Resilience4j
  • API 网关:Spring Cloud Gateway
  • 链路追踪:Sleuth + Zipkin
  • 数据库:MySQL 8.x
  • ORM 框架:MyBatis-Plus
  • 消息队列:RabbitMQ(可选,用于异步通信、解耦)
  • 部署环境:Docker + Kuber***es(可选,用于容器化部署和编排)

2. 项目结构设计

microservice-demo/
├── microservice-***mon/          # 公共模块(工具类、实体类、常量)
├── microservice-gateway/         # API 网关服务
├── microservice-user/            # 用户服务
├── microservice-order/           # 订单服务
├── microservice-product/         # 商品服务
└── pom.xml                       # 父工程 pom(统一管理依赖版本)

3. 父工程搭建(Maven)

<!-- pom.xml -->
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.6.13</version> <!-- Spring Boot 版本 -->
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>***.example</groupId>
    <artifactId>microservice-demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>microservice-demo</name>
    <description>Spring Cloud 微服务示例项目</description>
    <packaging>pom</packaging> <!-- 父工程打包类型为 pom -->
    
    <!-- 统一管理依赖版本 -->
    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>2021.0.5</spring-cloud.version> <!-- Spring Cloud 版本 -->
        <spring-cloud-alibaba.version>2021.0.5.0</spring-cloud-alibaba.version> <!-- Spring Cloud Alibaba 版本 -->
    </properties>
    
    <!-- 依赖管理 -->
    <dependencyManagement>
        <dependencies>
            <!-- Spring Cloud 依赖 -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!-- Spring Cloud Alibaba 依赖 -->
            <dependency>
                <groupId>***.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${spring-cloud-alibaba.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    
    <dependencies>
        <!-- Spring Boot Web 依赖(公共) -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- Spring Boot Test 依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    
    <!-- 构建配置 -->
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

4. 公共模块搭建(microservice-***mon)

  • 核心功能:提供跨服务共享的工具类、实体类、常量、异常定义等。
  • 依赖配置
<!-- microservice-***mon/pom.xml -->
<dependencies>
    <!-- Lombok 简化实体类 -->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
    <!-- Spring Boot Validation 数据校验 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-validation</artifactId>
    </dependency>
    <!-- 自定义异常相关 -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-web</artifactId>
    </dependency>
</dependencies>
  • 示例代码
    • 实体类 UserDTO.java
package ***.example.***mon.dto;

import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;

@Data
public class UserDTO {
    private Long id;
    
    @NotBlank(message = "用户名不能为空")
    private String username;
    
    @NotBlank(message = "密码不能为空")
    private String password;
    
    @NotNull(message = "年龄不能为空")
    private Integer age;
}
  • 自定义异常 BusinessException.java
package ***.example.***mon.exception;

import lombok.Data;

@Data
public class BusinessException extends RuntimeException {
    private Integer code;
    private String message;
    
    public BusinessException(Integer code, String message) {
        this.code = code;
        this.message = message;
    }
}

5. 服务模块搭建(以用户服务为例)

  • 依赖配置
<!-- microservice-user/pom.xml -->
<dependencies>
    <!-- 公共模块依赖 -->
    <dependency>
        <groupId>***.example</groupId>
        <artifactId>microservice-***mon</artifactId>
        <version>${project.version}</version>
    </dependency>
    
    <!-- Spring Cloud Nacos 服务发现依赖 -->
    <dependency>
        <groupId>***.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>
    
    <!-- Spring Cloud Nacos 配置中心依赖 -->
    <dependency>
        <groupId>***.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
    </dependency>
    
    <!-- OpenFeign 依赖(用于服务调用) -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>
    
    <!-- Resilience4j 熔断降级依赖 -->
    <dependency>
        <groupId>io.github.resilience4j</groupId>
        <artifactId>resilience4j-spring-boot2</artifactId>
    </dependency>
    
    <!-- MySQL 驱动 -->
    <dependency>
        <groupId>***.mysql</groupId>
        <artifactId>mysql-connector-j</artifactId>
        <scope>runtime</scope>
    </dependency>
    
    <!-- MyBatis-Plus -->
    <dependency>
        <groupId>***.baomidou</groupId>
        <artifactId>mybatis-plus-boot-starter</artifactId>
        <version>3.5.3.1</version>
    </dependency>
</dependencies>
  • 配置文件
    • bootstrap.yml(优先级高于 application.yml,用于配置中心相关):
spring:
  application:
    name: user-service # 服务名(需与 Nacos 配置中心的配置文件名对应)
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848 # Nacos 注册中心地址
      config:
        server-addr: 127.0.0.1:8848 # Nacos 配置中心地址
        file-extension: yaml # 配置文件格式
        namespace: dev # 环境隔离(开发环境)
  • application.yml(应用自身配置):
server:
  port: 8081 # 服务端口

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/microservice_user?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
    username: root
    password: 123456
    driver-class-name: ***.mysql.cj.jdbc.Driver

mybatis-plus:
  mapper-locations: classpath:mapper/*.xml # Mapper 映射文件路径
  type-aliases-package: ***.example.user.entity # 实体类别名扫描包
  configuration:
    map-underscore-to-camel-case: true # 下划线转驼峰

# Resilience4j 配置
resilience4j:
  circuitbreaker:
    instances:
      userService: # 熔断实例名(需与 @CircuitBreaker 注解的 name 对应)
        slidingWindowSize: 10 # 滑动窗口大小
        failureRateThreshold: 50 # 失败率阈值(超过 50% 触发熔断)
        waitDurationInOpenState: 10000 # 熔断后等待时间(10 秒后尝试恢复)
  retry:
    instances:
      userService:
        maxRetryAttempts: 3 # 最大重试次数
        waitDuration: 1000 # 重试间隔(1 秒)
  • 启动类
package ***.example.user;

import org.mybatis.spring.annotation.MapperScan;
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 // 启用服务发现(Spring Cloud 2020 后可省略)
@EnableFeignClients // 启用 OpenFeign
@MapperScan("***.example.user.mapper") // 扫描 Mapper 接口
public class UserServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(UserServiceApplication.class, args);
        System.out.println("用户服务启动成功!");
    }
}

四、核心组件实战

1. 服务注册与发现(Nacos)

  • Nacos 安装与启动
    1. 下载 Nacos 安装包(https://github.***/alibaba/nacos/releases);
    2. 解压后进入 bin 目录,执行启动命令:
      • Windows:startup.cmd -m standalone(单机模式);
      • Linux/Mac:sh startup.sh -m standalone
    3. 访问 Nacos 控制台(http://localhost:8848/nacos),默认用户名/密码:nacos/nacos。
  • 服务注册
    • 各服务模块引入 spring-cloud-starter-alibaba-nacos-discovery 依赖;
    • bootstrap.yml 中配置 Nacos 注册中心地址;
    • 启动服务后,在 Nacos 控制台的「服务管理 → 服务列表」中可看到注册的服务。
  • 服务发现
    • 通过 OpenFeign 调用其他服务时,直接使用服务名作为 URL 前缀,Nacos 会自动解析为具体的服务实例地址。

2. 配置中心(Nacos Config)

  • Nacos 配置添加
    1. 进入 Nacos 控制台,「配置管理 → 配置列表」,点击「+」添加配置;
    2. 配置信息:
      • Data ID:user-service-dev.yaml(格式:服务名-环境-文件后缀,与 bootstrap.yml 配置对应);
      • Group:默认 DEFAULT_GROUP
      • 配置内容:
# 数据库配置(可覆盖 application.yml 中的配置)
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/microservice_user?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
    username: root
    password: 123456

# 自定义配置
user:
  name: "张三"
  age: 25
  • 配置动态更新
    • 在业务类中使用 @Value 注解注入配置,结合 @RefreshScope 实现动态更新:
package ***.example.user.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("/user")
@RefreshScope // 启用配置动态刷新
public class UserController {
    
    @Value("${user.name}")
    private String userName;
    
    @Value("${user.age}")
    private Integer userAge;
    
    @GetMapping("/config")
    public String getConfig() {
        return "用户名:" + userName + ",年龄:" + userAge;
    }
}
  • 修改 Nacos 中的配置后,无需重启服务,直接访问 /user/config 即可看到最新配置。

3. 服务调用(OpenFeign + Ribbon)

  • 定义 Feign 接口(用户服务调用商品服务)
package ***.example.user.feign;

import ***.example.***mon.dto.ProductDTO;
import ***.example.user.fallback.ProductFeignFallback;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

@FeignClient(
        name = "product-service", // 目标服务名(Nacos 中注册的服务名)
        fallback = ProductFeignFallback.class // 降级处理类
)
public interface ProductFeignClient {
    
    @GetMapping("/product/{id}")
    ProductDTO getProductById(@PathVariable("id") Long id);
}
  • 降级处理类
package ***.example.user.fallback;

import ***.example.***mon.dto.ProductDTO;
import ***.example.user.feign.ProductFeignClient;
import org.springframework.stereotype.***ponent;

@***ponent
public class ProductFeignFallback implements ProductFeignClient {
    @Override
    public ProductDTO getProductById(Long id) {
        // 降级逻辑:返回默认商品信息
        ProductDTO productDTO = new ProductDTO();
        productDTO.setId(id);
        productDTO.setName("默认商品");
        productDTO.setPrice(0.0);
        return productDTO;
    }
}
  • 业务调用
package ***.example.user.service;

import ***.example.***mon.dto.ProductDTO;
import ***.example.user.feign.ProductFeignClient;
import io.github.resilience4j.circuitbreaker.annotation.CircuitBreaker;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class UserService {
    
    @Autowired
    private ProductFeignClient productFeignClient;
    
    // 启用熔断降级,指定熔断实例名
    @CircuitBreaker(name = "userService", fallbackMethod = "getUserFallback")
    public String getUserInfo(Long userId, Long productId) {
        // 调用商品服务
        ProductDTO productDTO = productFeignClient.getProductById(productId);
        // 模拟获取用户信息
        return "用户ID:" + userId + ",购买商品:" + productDTO.getName();
    }
    
    // 降级方法(参数和返回值需与原方法一致)
    public String getUserFallback(Long userId, Long productId, Exception e) {
        return "用户ID:" + userId + ",获取商品信息失败(" + e.getMessage() + "),已启用降级策略";
    }
}

4. API 网关(Spring Cloud Gateway)

  • 路由配置(application.yml)
spring:
  cloud:
    gateway:
      routes:
        # 用户服务路由
        - id: user-service-route
          uri: lb://user-service # 目标服务名(lb 表示负载均衡)
          predicates:
            - Path=/user/** # 路径匹配规则
          filters:
            - RewritePath=/user/(?<path>.*), /$\{path} # 路径重写(去掉 /user 前缀)
            - name: RequestRateLimiter # 限流过滤器
              args:
                redis-rate-limiter.replenishRate: 10 # 令牌桶填充速率(每秒 10 个)
                redis-rate-limiter.burstCapacity: 20 # 令牌桶容量(最大 20 个)
        
        # 订单服务路由
        - id: order-service-route
          uri: lb://order-service
          predicates:
            - Path=/order/**
          filters:
            - RewritePath=/order/(?<path>.*), /$\{path}
  • 全局过滤器(认证授权示例)
package ***.example.gateway.filter;

import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import reactor.core.publisher.Mono;

@Configuration
public class GlobalFilterConfig {
    
    @Bean
    @Order(-1) // 优先级(数值越小,优先级越高)
    public GlobalFilter authFilter() {
        return (exchange, chain) -> {
            // 获取请求头中的 Token
            String token = exchange.getRequest().getHeaders().getFirst("Authorization");
            if (token == null || !token.startsWith("Bearer ")) {
                // 无 Token 或 Token 格式不正确,返回 401
                exchange.getResponse().setStatusCode(org.springframework.http.HttpStatus.UNAUTHORIZED);
                return exchange.getResponse().set***plete();
            }
            
            // 验证 Token(此处简化,实际需调用认证服务)
            String realToken = token.substring(7);
            if (!"valid_token".equals(realToken)) {
                exchange.getResponse().setStatusCode(org.springframework.http.HttpStatus.FORBIDDEN);
                return exchange.getResponse().set***plete();
            }
            
            // Token 验证通过,继续向下游服务转发
            return chain.filter(exchange);
        };
    }
}

5. 服务链路追踪(Sleuth + Zipkin)

  • Zipkin 安装与启动
    1. 下载 Zipkin Jar 包(https://search.maven.org/artifact/io.zipkin/zipkin-server);
    2. 执行启动命令:java -jar zipkin-server-2.24.3-exec.jar
    3. 访问 Zipkin 控制台(http://localhost:9411)。
  • 各服务集成 Sleuth + Zipkin
    • 引入依赖:
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-sleuth-zipkin</artifactId>
</dependency>
  • 配置 application.yml
spring:
  sleuth:
    sampler:
      probability: 1.0 # 采样率(1.0 表示全采样,生产环境可调整为 0.1)
  zipkin:
    base-url: http://localhost:9411 # Zipkin 服务器地址
  • 链路追踪演示
    1. 启动网关、用户服务、商品服务;
    2. 通过网关访问用户服务的接口(如 http://localhost:8080/user/info?userId=1&productId=1);
    3. 访问 Zipkin 控制台,在「Find Traces」中可看到请求的链路信息,包括调用路径、各服务耗时、状态等。

五、微服务高级特性

1. 服务熔断与降级(Resilience4j 进阶)

  • 熔断状态机
    • 关闭状态(Closed):正常接收请求,记录失败率;
    • 打开状态(Open):失败率超过阈值,触发熔断,拒绝所有请求;
    • 半开状态(Half-Open):熔断后等待一段时间,允许少量请求尝试,若成功则恢复关闭状态,否则继续保持打开状态。
  • 限流配置
resilience4j:
  ratelimiter:
    instances:
      userService:
        limitForPeriod: 10 # 每周期最大请求数
        limitRefreshPeriod: 1000ms # 周期刷新时间(1 秒)
        timeoutDuration: 1000ms # 请求超时时间(1 秒)
  • 注解使用
import io.github.resilience4j.ratelimiter.annotation.RateLimiter;

@Service
public class UserService {
    
    // 限流注解
    @RateLimiter(name = "userService", fallbackMethod = "getUserRateLimitFallback")
    public String getUserInfoByRateLimit(Long userId) {
        return "用户ID:" + userId + ",请求成功";
    }
    
    // 限流降级方法
    public String getUserRateLimitFallback(Long userId, Exception e) {
        return "用户ID:" + userId + ",请求过于频繁,请稍后再试";
    }
}

2. 分布式事务(Seata)

  • 核心概念
    • 事务协调器(TC):协调全局事务的提交或回滚;
    • 事务管理器(TM):发起全局事务,定义事务的范围;
    • 资源管理器(RM):管理本地事务资源,参与全局事务的提交或回滚。
  • Seata 安装与配置
    1. 下载 Seata 安装包(https://github.***/seata/seata/releases);
    2. 解压后修改 conf/registry.conf,配置 Nacos 作为注册中心和配置中心;
    3. 启动 Seata Server:bin/seata-server.sh(Linux/Mac)或 bin/seata-server.bat(Windows)。
  • 项目集成 Seata
    • 引入依赖:
<dependency>
    <groupId>***.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
</dependency>
  • 配置 application.yml
seata:
  application-id: ${spring.application.name}
  tx-service-group: my_test_tx_group # 事务组名称(需与 Seata Server 配置一致)
  registry:
    type: nacos
    nacos:
      server-addr: 127.0.0.1:8848
      namespace: ""
      group: SEATA_GROUP
  config:
    type: nacos
    nacos:
      server-addr: 127.0.0.1:8848
      namespace: ""
      group: SEATA_GROUP
  • 分布式事务示例(AT 模式)
    • 订单服务(TM):
package ***.example.order.service;

import ***.alibaba.fastjson.JSON;
import ***.example.***mon.dto.OrderDTO;
import ***.example.order.entity.Order;
import ***.example.order.mapper.OrderMapper;
import ***.example.order.feign.UserFeignClient;
import io.seata.spring.annotation.GlobalTransactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class OrderService {
    
    @Autowired
    private OrderMapper orderMapper;
    
    @Autowired
    private UserFeignClient userFeignClient;
    
    // 全局事务注解
    @GlobalTransactional(rollbackFor = Exception.class)
    public void createOrder(OrderDTO orderDTO) {
        // 1. 创建订单(本地事务)
        Order order = new Order();
        order.setUserId(orderDTO.getUserId());
        order.setProductId(orderDTO.getProductId());
        order.setAmount(orderDTO.getAmount());
        orderMapper.insert(order);
        
        // 2. 调用用户服务扣减余额(远程事务)
        boolean deductSu***ess = userFeignClient.deductBalance(orderDTO.getUserId(), orderDTO.getAmount());
        if (!deductSu***ess) {
            // 扣减失败,触发全局事务回滚
            throw new RuntimeException("用户余额不足,创建订单失败");
        }
        
        // 3. 模拟异常(测试回滚)
        // int i = 1 / 0;
    }
}
  • 用户服务(RM):
package ***.example.user.service;

import ***.example.user.entity.User;
import ***.example.user.mapper.UserMapper;
import io.seata.core.context.RootContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class UserService {
    
    @Autowired
    private UserMapper userMapper;
    
    // 本地事务注解(需与 Seata 集成)
    @Transactional
    public boolean deductBalance(Long userId, Double amount) {
        // 验证全局事务是否存在
        if (RootContext.getXID() == null) {
            throw new RuntimeException("未检测到全局事务");
        }
        
        User user = userMapper.selectById(userId);
        if (user == null) {
            throw new RuntimeException("用户不存在");
        }
        
        if (user.getBalance() < amount) {
            return false;
        }
        
        // 扣减余额
        user.setBalance(user.getBalance() - amount);
        userMapper.updateById(user);
        return true;
    }
}

3. 服务监控(Spring Boot Admin)

  • Spring Boot Admin 服务端搭建
    • 依赖配置:
<dependencies>
    <dependency>
        <groupId>de.codecentric</groupId>
        <artifactId>spring-boot-admin-starter-server</artifactId>
        <version>2.6.10</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-***flix-eureka-client</artifactId>
    </dependency>
</dependencies>
  • 启动类:
package ***.example.admin;

import de.codecentric.boot.admin.server.config.EnableAdminServer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@SpringBootApplication
@EnableAdminServer // 启用 Spring Boot Admin 服务端
@EnableDiscoveryClient
public class AdminServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(AdminServerApplication.class, args);
    }
}
  • 客户端集成
    • 各服务引入依赖:
<dependency>
    <groupId>de.codecentric</groupId>
    <artifactId>spring-boot-admin-starter-client</artifactId>
    <version>2.6.10</version>
</dependency>
  • 配置 application.yml
spring:
  boot:
    admin:
      client:
        url: http://localhost:8088 # Spring Boot Admin 服务端地址
        username: admin # 服务端认证用户名(若配置)
        password: admin123 # 服务端认证密码(若配置)

management:
  endpoints:
    web:
      exposure:
        include: "*" # 暴露所有监控端点
  endpoint:
    health:
      show-details: always # 显示健康详情
  • 监控功能
    • 访问 Spring Boot Admin 控制台(http://localhost:8088),可查看各服务的健康状态、内存使用、CPU 占用、日志、接口调用情况等。

六、微服务部署与运维

1. Docker 容器化部署

  • 服务 Dockerfile 示例(用户服务)
# 基础镜像(Java 8)
FROM openjdk:8-jdk-alpine

# 维护者信息
LABEL maintainer="example@163.***"

# 暴露端口
EXPOSE 8081

# 添加 JAR 包
ADD target/microservice-user-0.0.1-SNAPSHOT.jar user-service.jar

# 启动命令
ENTRYPOINT ["java", "-jar", "/user-service.jar"]
  • 构建 Docker 镜像
# 进入服务模块目录
cd microservice-user
# 构建 JAR 包
mvn clean package -Dmaven.test.skip=true
# 构建 Docker 镜像
docker build -t user-service:1.0 .
  • 运行 Docker 容器
docker run -d -p 8081:8081 --name user-service \
--link nacos:nacos \
--link zipkin:zipkin \
-e SPRING_CLOUD_NACOS_DISCOVERY_SERVER-ADDR=nacos:8848 \
-e SPRING_CLOUD_NACOS_CONFIG_SERVER-ADDR=nacos:8848 \
-e SPRING_ZIPKIN_BASE-URL=http://zipkin:9411 \
user-service:1.0

2. Kuber***es 编排部署

  • Deployment 配置示例(user-service-deployment.yaml)
apiVersion: apps/v1
kind: Deployment
metadata:
  name: user-service
  namespace: microservice
spec:
  replicas: 2 # 副本数
  selector:
    matchLabels:
      app: user-service
  template:
    metadata:
      labels:
        app: user-service
    spec:
      containers:
      - name: user-service
        image: user-service:1.0
        ports:
        - containerPort: 8081
        env:
        - name: SPRING_CLOUD_NACOS_DISCOVERY_SERVER-ADDR
          value: "nacos-service:8848"
        - name: SPRING_CLOUD_NACOS_CONFIG_SERVER-ADDR
          value: "nacos-service:8848"
        - name: SPRING_ZIPKIN_BASE-URL
          value: "http://zipkin-service:9411"
        resources:
          limits:
            memory: "1Gi"
            cpu: "500m"
          requests:
            memory: "512Mi"
            cpu: "200m"
        livenessProbe: # 存活探针
          httpGet:
            path: /actuator/health
            port: 8081
          initialDelaySeconds: 60
          periodSeconds: 10
        readinessProbe: # 就绪探针
          httpGet:
            path: /actuator/health
            port: 8081
          initialDelaySeconds: 30
          periodSeconds: 5
  • Service 配置示例(user-service-service.yaml)
apiVersion: v1
kind: Service
metadata:
  name: user-service
  namespace: microservice
spec:
  selector:
    app: user-service
  ports:
  - port: 8081
    targetPort: 8081
  type: ClusterIP # 集群内部访问(若需外部访问,可改为 NodePort 或 LoadBalancer)
  • 部署命令
# 创建命名空间
kubectl create namespace microservice
# 部署 Deployment
kubectl apply -f user-service-deployment.yaml -n microservice
# 部署 Service
kubectl apply -f user-service-service.yaml -n microservice
# 查看部署状态
kubectl get pods -n microservice
kubectl get svc -n microservice

3. 日志收集(ELK)

  • 核心组件
    • Elasticsearch:存储日志数据;
    • Logstash:收集、过滤、转换日志数据,发送到 Elasticsearch;
    • Kibana:可视化展示日志数据,支持查询、分析。
  • Spring Boot 服务集成 Logback 输出 JSON 日志
    • 引入依赖:
<dependency>
    <groupId>***.logstash.logback</groupId>
    <artifactId>logstash-logback-encoder</artifactId>
    <version>7.2.0</version>
</dependency>
  • 配置 logback-spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <include resource="org/springframework/boot/logging/logback/defaults.xml"/>
    <include resource="org/springframework/boot/logging/logback/console-appender.xml"/>
    
    <!-- 输出 JSON 格式日志 -->
    <appender name="JSON_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>logs/${spring.application.name}.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>logs/${spring.application.name}-%d{yyyy-MM-dd}.log</fileNamePattern>
            <maxHistory>7</maxHistory>
        </rollingPolicy>
        <encoder class="***.logstash.logback.encoder.LogstashEncoder">
            <includeMdcKeyName>traceId</includeMdcKeyName>
            <includeMdcKeyName>spanId</includeMdcKeyName>
            <includeMdcKeyName>userId</includeMdcKeyName>
            <customFields>{"service":"${spring.application.name}"}</customFields>
        </encoder>
    </appender>
    
    <root level="INFO">
        <appender-ref ref="CONSOLE"/>
        <appender-ref ref="JSON_FILE"/>
    </root>
</configuration>
  • Logstash 配置(logstash.conf)
input {
  file {
    path => "/var/log/microservice/*.log" # 日志文件路径(Docker/K8s 挂载的日志目录)
    start_position => "beginning"
    sincedb_path => "/dev/null"
    codec => "json"
  }
}

filter {
  if [service] == "user-service" {
    mutate {
      add_field => { "[@metadata][index_prefix]" => "user-service" }
    }
  } else if [service] == "order-service" {
    mutate {
      add_field => { "[@metadata][index_prefix]" => "order-service" }
    }
  }
}

output {
  elasticsearch {
    hosts => ["elasticsearch:9200"] # Elasticsearch 地址
    index => "%{[@metadata][index_prefix]}-%{+YYYY.MM.dd}" # 索引名(按服务和日期拆分)
  }
  stdout { codec => rubydebug }
}

七、总结与展望

1. 微服务实践总结

  • 核心优势:微服务架构通过拆分业务、独立部署、灵活扩展,解决了单体应用的臃肿、僵化、难以维护等问题,适合复杂业务系统的开发与演进。
  • 关键挑战
    • 分布式系统的复杂性:服务间依赖、分布式事务、数据一致性等问题需重点解决;
    • 运维成本提升:微服务数量多,部署、监控、排查问题的难度增加;
    • 团队协作要求高:需明确服务边界、接口契约,避免重复开发。
  • 实践建议
    • 合理拆分服务:基于业务领域边界拆分,避免过度拆分(如一个小功能拆分为多个服务);
    • 优先解决核心问题:如服务注册发现、配置中心、熔断降级等基础能力,再逐步引入分布式事务、监控等高级特性;
    • 自动化运维:借助 Docker、K8s、CI/CD 工具,实现部署、扩容、回滚的自动化,降低运维成本。

2. 微服务未来趋势

  • 云原生架构:微服务与云原生技术(如容器化、服务网格、Serverless)深度融合,实现更高效的资源利用、更灵活的弹性伸缩;
  • 服务网格(Istio):将服务间的通信、流量控制、安全认证等功能从业务代码中剥离,由服务网格统一管理,简化微服务开发;
  • 低代码/无代码平台:结合微服务架构,提供可视化开发、拖拽式配置,降低微服务的开发门槛;
  • AI 驱动的运维:通过 AI 技术实现日志分析、故障预测、智能扩容,提升微服务系统的稳定性和运维效率。

微服务架构不是银弹,需结合业务场景和团队能力合理选择。在实践过程中,应持续优化服务设计、完善技术体系,逐步构建稳定、高效、可扩展的微服务系统。

转载请说明出处内容投诉
CSS教程网 » 零基础学习:Spring Cloud 微服务全栈实践

发表评论

欢迎 访客 发表评论

一个令你着迷的主题!

查看演示 官网购买