Java高级全套教程(九)—— SpringCloud超详细实战详解

Java高级全套教程(九)------ SpringCloud超详细实战详解

前言

Spring Cloud 是目前企业主流的微服务一站式解决方案,基于 Spring Boot 二次封装,屏蔽了分布式系统开发的各类复杂问题,包含服务注册发现、负载均衡、远程调用、容错熔断、配置管理等全套核心能力。本教程将从零拆解微服务架构演进逻辑、Spring Cloud 核心原理、主流组件实战落地,所有代码均为原创实战代码,适配新版 Spring Cloud 技术栈,摒弃老旧 Netflix 停更组件,贴合企业生产规范。

第一章 微服务架构完整演进体系

互联网业务体量不断扩张,系统架构随之迭代升级,整体分为四个核心阶段,每个阶段对应不同的业务场景、优势与痛点,也是 Spring Cloud 诞生的核心背景。

1.1 单体架构(初始阶段)

1.1.1 架构概念

单体架构是互联网最原始的架构模式,将表现层、业务逻辑层、数据访问层所有业务代码整合在一个项目中,整体打包、统一部署在单台服务器,所有功能共用服务器硬件资源。

1.1.2 适用场景

初创项目、小型网站、用户量少、并发低、迭代节奏慢的业务场景,早期个人/小团队开发首选。

1.1.3 核心优缺点

优点:开发门槛极低、项目结构简单、调试便捷、部署成本低、单次请求内部调用无网络损耗,响应速度极快;3-5人小团队可快速迭代上线。

缺点:服务器 CPU、内存、磁盘资源存在硬性瓶颈,并发承载能力有限;业务耦合严重,新增功能需改动整体代码,牵一发而动全身;局部模块故障会导致整个系统瘫痪;无法针对高并发模块单独扩容。

1.2 垂直应用架构(扩容阶段)

1.2.1 架构概念

随着业务流量上涨,单体架构无法承载并发压力,于是将单一单体项目按业务模块垂直拆分为多个独立单体应用,通过 Nginx 实现请求负载分发,多个应用独立部署,共享数据库与公共资源。

1.2.2 核心优缺点

优点:解决了单体架构的并发瓶颈,多实例分担流量压力,单模块故障不会影响整体业务;项目拆分后,团队可分工开发,迭代效率提升。

缺点:新增 Nginx 转发链路,单次请求响应速度略有下降;各应用共享数据库,数据耦合严重,独立扩展能力差;模块间通信无标准化方案,系统复杂度持续升高。

1.3 分布式架构(精细化拆分阶段)

1.3.1 架构概念

彻底打破数据库共享模式,基于业务领域对系统进行精细化拆分,将核心业务拆分为独立的分布式服务(用户服务、订单服务、商品服务、支付服务等),每个服务独立数据库、独立部署、独立运行,服务之间通过网络协议完成远程通信。

1.3.2 核心特点

业务高内聚、低耦合,单一服务只负责单一领域业务;高并发核心服务可单独扩容升级;彻底解决数据耦合问题;但同时衍生出分布式通病:服务治理混乱、远程调用不可控、无容错机制、服务依赖混乱。

1.4 微服务架构(标准化治理阶段)

1.4.1 核心定义

微服务是分布式架构的标准化升级版,是一套可独立部署、独立迭代、独立运维的轻量化服务集群。拆分粒度更细,所有服务遵循高内聚松耦合原则,通过轻量化 HTTP 协议通信,搭配完整的服务治理体系。

1.4.2 微服务核心组件体系

完整的微服务架构必须具备八大核心能力:服务注册发现、负载均衡、声明式远程调用、熔断限流降级、网关路由、分布式配置、链路追踪、服务监控。

1.4.3 生活化类比理解

单体架构=夫妻小摊,一人多职;垂直架构=小型饭店,分工初步拆分;分布式架构=中型酒店,岗位细分;微服务架构=五星级大酒店,全岗位专业化分工、统一调度、容错保障、标准化管理。

第二章 Spring Cloud 核心原理与技术栈迭代

2.1 Spring Cloud 核心定义

Spring Cloud 是一套基于 Spring Boot 构建的微服务一站式开发框架,并非单一组件,而是一套完整的组件生态。它标准化解决了分布式系统开发中的各类通用问题,大幅降低微服务开发门槛,让开发者专注业务实现。

核心能力覆盖:服务注册与发现、负载均衡、远程服务调用、熔断限流、分布式配置、API 网关、服务总线、链路监控等。

2.2 Spring Cloud 与 Spring Boot 关系

1、Spring Boot:微服务单体基础框架,负责快速构建独立、可运行的 Java 应用,简化 Spring 配置;

2、Spring Cloud:微服务分布式协调框架,基于 Spring Boot 所有单体服务,解决服务之间的协作、治理、容错问题;

3、绑定关系:Spring Cloud 依赖 Spring Boot 运行,二者版本严格对应,版本不匹配会直接导致项目启动报错、组件失效。

2.3 Spring Cloud 技术栈迭代历程

2.3.1 初代 Netflix 生态(旧版)

Spring Cloud 早期核心组件均由 Netflix 公司开源贡献,包含 Eureka(注册中心)、Ribbon(负载均衡)、Feign(远程调用)、Hystrix(熔断限流)、Zuul(网关)。

关键节点:2018 年 Netflix 宣布所有开源微服务组件停止更新、进入维护模式,不再迭代新功能。

2.3.2 新版标准化生态(当前主流)

Spring 官方逐步淘汰 Netflix 组件,推出自研组件 + Spring Cloud Alibaba 组件替代方案,也是目前企业生产环境主流技术栈:

旧版 Netflix 组件 新版替代组件 组件作用
Eureka Nacos 服务注册与发现中心
Ribbon Spring Cloud LoadBalancer 客户端负载均衡
Feign OpenFeign 声明式远程服务调用
Hystrix Sentinel / Resilience4j 服务熔断、限流、降级
Zuul Spring Cloud Gateway 统一 API 网关
Config Nacos / Apollo 分布式配置中心

2.4 Spring Cloud 版本规范

2.4.1 版本命名规则

2020.0 版本之前:采用伦敦地铁站名称命名(Angel、Brixton、Camden 等),按字母顺序迭代;

2020.0 版本及之后:改为日历化命名,格式为 年份.季度.修订号,更直观易懂。

2.4.2 版本标识含义

1、GA:正式发布版,生产环境推荐使用,稳定无重大 Bug;

2、SR:修正版,基于正式版修复已知问题;

3、RC:候选版本,基本稳定,不建议生产使用;

4、PRE:预览测试版,仅用于内部测试;

5、SNAPSHOT:快照版,持续迭代更新,稳定性差。

第三章 微服务工程环境搭建(企业标准架构)

企业级 Spring Cloud 项目均采用聚合父工程 + 多子模块架构,通过父工程统一管理依赖版本,杜绝版本冲突,规范项目结构。

3.1 工程整体结构规划

本次实战工程结构如下,完全贴合企业开发规范:

spring-cloud-study(父工程,pom打包)

├── cloud-eureka-server(注册中心服务)

├── cloud-user-provider(用户服务-生产者)

├── cloud-order-consumer(订单服务-消费者)

└── cloud-common-core(公共依赖模块)

3.2 父工程全局依赖配置

父工程核心作用:锁定所有子模块依赖版本,子模块无需重复定义版本号,统一项目规范。

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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.cloud</groupId>
    <artifactId>spring-cloud-study</artifactId>
    <version>1.0.0</version>
    <packaging>pom</packaging>
    <modules>
        <module>cloud-eureka-server</module>
        <module>cloud-user-provider</module>
        <module>cloud-order-consumer</module>
        <module>cloud-common-core</module>
    </modules>

    <!-- 全局统一版本配置 -->
    <properties>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <spring.boot.version>2.6.13</spring.boot.version>
        <spring.cloud.version>2021.0.5</spring.cloud.version>
        <lombok.version>1.18.30</lombok.version>
    </properties>

    <!-- 依赖版本锁定管理 -->
    <dependencyManagement>
        <dependencies>
            <!-- SpringBoot 全局依赖 -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring.boot.version}</version>
                pom<scope>import</scope>
            </dependency>

            <!-- SpringCloud 全局依赖 -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring.cloud.version}</version>
                pom<scope>import</scope>
            </dependency>

            <!-- 公共工具依赖 -->
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>${lombok.version}</version>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <!-- 全局公共依赖 -->
    <dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

3.3 公共核心模块搭建

创建 cloud-common-core 模块,存放公共实体类、工具类、统一返回结果,所有业务模块依赖此模块,减少代码冗余。

3.3.1 统一返回结果实体类

java 复制代码
package com.cloud.common.result;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * 全局统一返回结果工具类
 * @param <T> 返回数据泛型
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Result<T> {
    // 响应状态码 200成功 500失败
    private Integer code;
    // 响应提示信息
    private String msg;
    // 响应数据
    private T data;

    // 成功响应-带数据
    public static <T> Result<T> success(T data){
        return new Result<>(200,"操作成功",data);
    }

    // 成功响应-无数据
    public static <T> Result<T> success(){
        return new Result<>(200,"操作成功",null);
    }

    // 失败响应
    public static <T> Result<T> error(String msg){
        return new Result<>(500,msg,null);
    }
}

第四章 服务注册与发现(Eureka 实战)

服务注册与发现是微服务治理的核心基础,解决微服务集群中服务地址动态管理、服务自动感知的问题。Eureka 是 Spring Cloud 经典注册中心组件,基于 AP 架构,高可用、容错性强。

4.1 Eureka 核心架构角色

1、Eureka Server:注册中心服务端,独立部署,负责接收服务注册、维护服务清单、心跳检测;

2、Eureka Client:客户端,所有微服务都是客户端,分为服务提供者、服务消费者;

3、核心流程:服务启动注册 → 服务端维护清单 → 消费者拉取清单 → 定时心跳续约。

4.2 单机 Eureka 注册中心搭建

4.2.1 模块依赖配置

新建 cloud-eureka-server 模块,引入 Eureka 服务端专属依赖

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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <groupId>com.cloud</groupId>
        <artifactId>spring-cloud-study</artifactId>
        <version>1.0.0</version>
    </parent>

    <modelVersion>4.0.0</modelVersion><artifactId>cloud-eureka-server</artifactId>

    <dependencies>
        <!-- Eureka服务端核心依赖 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
    </dependencies>
</project>

4.2.2 全局配置文件 application.yml

yaml 复制代码
server:
  port: 8761 # Eureka默认端口

eureka:
  client:
    # 不将当前注册中心服务注册到自身
    register-with-eureka: false
    # 不主动拉取注册服务列表
    fetch-registry: false
    # 注册中心交互地址
    service-url:
      defaultZone: http://localhost:8761/eureka/
# 关闭自我保护(测试环境使用,生产环境开启)
server:
  enable-self-preservation: false

4.2.3 启动类配置

java 复制代码
package com.cloud.eureka;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

/**
 * Eureka注册中心启动类
 * 注解@EnableEurekaServer:开启注册中心服务端功能
 */
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(EurekaServerApplication.class,args);
        System.out.println("===== Eureka注册中心启动成功 端口:8761 =====");
    }
}

4.3 服务提供者搭建(用户服务)

4.3.1 模块依赖

新建 cloud-user-provider 服务提供者模块

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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   <parent>
        <groupId>com.cloud</groupId>
        <artifactId>spring-cloud-study</artifactId>
        <version>1.0.0</version>
    </parent>

    <modelVersion>4.0.0</modelVersion>
    <artifactId>cloud-user-provider</artifactId>

    <dependencies>
        <!-- web核心依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- Eureka客户端依赖 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <!-- 服务监控完善依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <!-- 引入公共模块 -->
        <dependency>
            <groupId>com.cloud</groupId>
            <artifactId>cloud-common-core</artifactId>
            <version>1.0.0</version>
        </dependency>
    </dependencies>
</project>

4.3.2 服务配置文件

yaml 复制代码
server:
  port: 8010

spring:
  application:
    name: cloud-user-provider # 服务唯一名称,注册中心识别标识

eureka:
  client:
    # 开启服务注册
    register-with-eureka: true
    # 开启服务发现
    fetch-registry: true
    service-url:
      defaultZone: http://localhost:8761/eureka/
  instance:
    # 自定义服务实例ID,区分多实例
    instance-id: user-provider-8010
    # 显示IP地址
    prefer-ip-address: true

4.3.3 服务启动类与业务接口

启动类:

java 复制代码
package com.cloud.user;

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

/**
 * 用户服务提供者启动类
 * EnableDiscoveryClient:开启服务注册发现功能
 */
@SpringBootApplication
@EnableDiscoveryClient
public class UserProviderApplication {
    public static void main(String[] args) {
        SpringApplication.run(UserProviderApplication.class,args);
        System.out.println("===== 用户服务提供者启动成功 =====");
    }
}

业务 Controller 接口:

java 复制代码
package com.cloud.user.controller;

import com.cloud.common.result.Result;
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("/user")
public class UserController {

    /**
     * 根据用户ID查询用户信息
     */
    @GetMapping("/get/{userId}")
    public Result<String> getUserInfo(@PathVariable Long userId){
        String userData = "用户服务8010:查询ID为【"+userId+"】的用户,姓名:张三,手机号:13800138000";
        return Result.success(userData);
    }

    /**
     * 模拟超时接口,用于后续熔断测试
     */
    @GetMapping("/timeout")
    public Result<String> testTimeout() throws InterruptedException {
        // 模拟业务阻塞5秒
        Thread.sleep(5000);
        return Result.success("用户服务正常响应");
    }
}

4.4 服务消费者搭建(订单服务)

4.4.1 模块配置与依赖

新建 cloud-order-consumer 消费者模块,依赖配置与服务提供者基本一致,端口改为8020

4.4.2 RestTemplate 远程调用配置

消费者通过 RestTemplate 实现基础远程调用,后续整合负载均衡与 OpenFeign

java 复制代码
package com.cloud.order.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

/**
 * 远程调用工具配置类
 */
@Configuration
public class RestTemplateConfig {

    @Bean
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
}

4.4.3 订单消费业务接口

java 复制代码
package com.cloud.order.controller;

import com.cloud.common.result.Result;
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;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;

/**
 * 订单服务消费者接口
 */
@RestController
@RequestMapping("/order")
public class OrderController {

    @Resource
    private RestTemplate restTemplate;

    // 服务提供者注册名称
    private static final String USER_SERVICE_URL = "http://cloud-user-provider";

    @GetMapping("/create/{userId}")
    public Result<String> createOrder(@PathVariable Long userId){
        // 远程调用用户服务
        String url = USER_SERVICE_URL + "/user/get/" + userId;
        Result<String> userResult = restTemplate.getForObject(url, Result.class);
        String result = "订单创建成功,关联用户信息:" + userResult.getData();
        return Result.success(result);
    }
}

4.5 Eureka 核心机制详解

4.5.1 心跳续约机制

所有 Eureka 客户端默认每30秒向服务端发送一次心跳请求,证明服务存活;服务端接收心跳后更新服务状态。

4.5.2 服务剔除机制

服务端连续90秒未收到客户端心跳,判定服务失效,自动将该服务从注册列表中剔除,避免调用无效服务。

4.5.3 自我保护机制

Eureka 核心容错机制,默认开启。当短时间内大量服务心跳失效,服务端判定为网络抖动而非服务故障,不会剔除服务,避免大规模误删可用服务,保证系统高可用。

手动关闭配置:eureka.server.enable-self-preservation=false(仅测试环境使用)

4.6 Eureka 高可用集群搭建

单机 Eureka 存在单点故障,生产环境必须搭建集群,多节点互相注册、同步服务数据。

4.6.1 本地 Hosts 映射配置

修改 C:\Windows\System32\drivers\etc\hosts 文件,添加域名映射

Plain 复制代码
127.0.0.1 eureka-master
127.0.0.1 eureka-slave

4.6.2 双节点集群配置

节点1(8761)配置:互相注册至从节点

yaml 复制代码
server:
  port: 8761
eureka:
  client:
    register-with-eureka: true
    fetch-registry: true
    service-url:
      defaultZone: http://eureka-slave:8762/eureka/

节点2(8762)配置:互相注册至主节点

yaml 复制代码
server:
  port: 8762
eureka:
  client:
    register-with-eureka: true
    fetch-registry: true
    service-url:
      defaultZone: http://eureka-master:8761/eureka/

4.6.3 业务服务集群注册配置

所有生产者、消费者同时注册至两个注册中心,实现高可用

yaml 复制代码
eureka:
  client:
    service-url:
      defaultZone: http://eureka-master:8761/eureka/,http://eureka-slave:8762/eureka/

第五章 客户端负载均衡 LoadBalancer 实战

5.1 负载均衡核心概念

负载均衡是微服务流量分发的核心,解决多实例服务流量分配不均、单实例压力过大的问题。分为服务端负载均衡(Nginx)和客户端负载均衡(LoadBalancer)。

Spring Cloud 新版舍弃老旧 Ribbon,默认使用 LoadBalancer 作为客户端负载均衡组件,轻量、高效、适配新版生态。

5.2 LoadBalancer 核心优势

1、客户端本地负载均衡,无需中间代理,网络损耗更低;

2、天然整合 Spring Cloud 生态,无需额外配置;

3、支持轮询、随机两种主流策略,支持自定义扩展;

4、适配高可用集群,自动感知服务上下线。

5.3 负载均衡实战配置

5.3.1 开启负载均衡注解

在 RestTemplate 配置类上添加 @LoadBalanced 注解,开启客户端负载均衡能力

java 复制代码
package com.cloud.order.config;

import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

@Configuration
public class RestTemplateConfig {

    @Bean
    @LoadBalanced // 开启LoadBalancer负载均衡
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
}

5.3.2 负载均衡策略配置

LoadBalancer 默认轮询策略,可手动修改为随机策略

yaml 复制代码
# 全局负载均衡策略配置
spring:
  cloud:
    loadbalancer:
      rules:
        # 针对用户服务开启随机负载策略
        cloud-user-provider:
          random: true

5.4 负载均衡效果测试

1、启动两个用户服务实例(8010、8011);

2、启动订单消费者服务;

3、多次调用订单接口,请求会自动分发到两个用户服务实例,实现流量均衡。

第六章 声明式远程调用 OpenFeign 实战

OpenFeign 是 Spring Cloud 主流的声明式远程调用组件,替代原生 RestTemplate 繁琐的 URL 拼接调用方式,基于接口+注解实现远程调用,代码简洁、可读性强,天然集成负载均衡。

6.1 OpenFeign 核心优势

1、声明式调用:通过接口注解定义远程请求,无需手动拼接地址;

2、兼容 SpringMVC 注解,学习成本极低;

3、内置 LoadBalancer 负载均衡,自动实现多实例分发;

4、支持超时配置、日志打印、请求拦截、降级兜底。

6.2 OpenFeign 环境搭建

6.2.1 引入核心依赖

在订单消费者模块添加 OpenFeign 依赖

xml 复制代码
<!-- OpenFeign声明式远程调用 -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

6.2.2 启动类开启 Feign 功能

java 复制代码
package com.cloud.order;

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 // 开启OpenFeign远程调用功能
public class OrderConsumerApplication {
    public static void main(String[] args) {
        SpringApplication.run(OrderConsumerApplication.class,args);
        System.out.println("===== 订单消费者服务启动成功 =====");
    }
}

6.3 编写 Feign 远程调用接口

创建远程调用接口,绑定目标服务,方法签名与服务提供者接口完全一致

java 复制代码
package com.cloud.order.feign;

import com.cloud.common.result.Result;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

/**
 * 用户服务远程调用接口
 * FeignClient:指定调用的目标服务名称
 */
@FeignClient(value = "cloud-user-provider")
public interface UserFeignClient {

    /**
     * 远程调用用户查询接口
     */
    @GetMapping("/user/get/{userId}")
    Result<String> getUserInfo(@PathVariable("userId") Long userId);

    /**
     * 远程调用超时测试接口
     */
    @GetMapping("/user/timeout")
    Result<String> testTimeout();
}

6.4 改造订单控制器实现 Feign 调用

java 复制代码
package com.cloud.order.controller;

import com.cloud.common.result.Result;
import com.cloud.order.feign.UserFeignClient;
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;

import javax.annotation.Resource;

@RestController
@RequestMapping("/order")
public class OrderFeignController {

    @Resource
    private UserFeignClient userFeignClient;

    // Feign声明式调用
    @GetMapping("/feign/create/{userId}")
    public Result<String> feignCreateOrder(@PathVariable Long userId){
        Result<String> userResult = userFeignClient.getUserInfo(userId);
        String data = "Feign调用成功,创建订单完成:" + userResult.getData();
        return Result.success(data);
    }
}

6.5 OpenFeign 日志增强配置

开发环境开启完整日志,打印请求地址、请求头、请求体、响应数据,方便调试排错

6.5.1 日志配置类

java 复制代码
package com.cloud.order.config;

import feign.Logger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * Feign日志级别配置
 */
@Configuration
public class FeignLogConfig {

    @Bean
    public Logger.Level feignLoggerLevel(){
        // FULL级别:打印完整请求响应日志
        return Logger.Level.FULL;
    }
}

6.5.2 yml 日志开启配置

yaml 复制代码
# 开启Feign接口debug日志
logging:
  level:
    com.cloud.order.feign: debug

6.6 OpenFeign 超时机制配置

默认超时时间较短,高并发场景易超时,可自定义连接超时、读取超时时间,防止请求堆积引发服务雪崩

yaml 复制代码
# Feign超时全局配置
feign:
  client:
    config:
      default:
        connectTimeout: 3000 # 连接超时时间3秒
        readTimeout: 6000    # 读取超时时间6秒

第七章 服务雪崩与容错机制原理

7.1 服务雪崩核心原理

微服务之间存在强依赖关系,当下游核心服务故障、阻塞、超时时,上游服务大量请求会持续等待、重试,导致线程资源、内存资源被耗尽,进而引发上游服务瘫痪,故障逐级向上传递,最终导致整个微服务集群全部不可用,该现象即为服务雪崩。

7.2 雪崩产生的三大核心原因

1、服务提供者不可用:程序 Bug、服务器宕机、网络波动、并发过载、缓存击穿等;

2、重试放大流量:客户端超时自动重试、用户手动刷新,大幅增加故障服务流量压力;

3、调用者资源耗尽:同步阻塞等待导致线程池爆满,新请求无法处理,服务彻底瘫痪。

7.3 雪崩解决方案:熔断、降级、隔离

1、服务熔断:类似电路保险丝,故障率达到阈值自动熔断,停止调用故障服务,快速返回;

2、服务降级:系统繁忙时,主动关闭非核心业务,返回兜底数据,保障核心业务可用;

3、服务隔离:通过线程池、信号量隔离不同服务调用,避免单一故障拖垮整体服务。

7.4 新版容错组件选型

老旧 Hystrix 组件已停更,企业主流使用 Sentinel(阿里)、Resilience4j 作为熔断降级核心组件,轻量、稳定、功能更强大。

第八章 Sentinel 熔断降级完整实战(企业主流容错方案)

前文我们讲解了服务雪崩的危害与容错核心思想,目前Spring Cloud官方已全面弃用停止维护的Hystrix。Sentinel是阿里开源的轻量级流量控制组件,凭借低侵入、高性能、可视化控制台、功能全面的优势,成为国内企业微服务容错的首选方案。本章将基于现有微服务工程,从零实现Sentinel的服务熔断、接口降级、流量限流、异常兜底全套实战功能。

8.1 Sentinel 核心核心优势与核心概念

8.1.1 核心优势

1、轻量无依赖:单独Jar包即可运行,无需复杂中间件部署,接入成本极低;

2、全方位容错:支持熔断、降级、限流、热点流量控制、系统自适应保护、权限黑白名单

3、可视化控制台:实时监控服务流量、异常率、熔断状态,动态修改规则,无需重启服务;

4、高兼容性:完美适配Spring Cloud、Spring Cloud Alibaba生态,兼容OpenFeign、LoadBalancer;

5、高性能:单机每秒可支撑十万级QPS流量,几乎无性能损耗。

8.1.2 核心核心概念

资源:Sentinel管控的最小单元,所有被保护的接口、方法、代码段都称为资源;

规则:针对资源配置的限流、熔断、降级策略;

流量控制:限制接口QPS、并发线程数,防止瞬间流量打垮服务;

熔断降级:统计异常比例、响应耗时,自动熔断故障接口,快速兜底。

8.2 环境搭建与依赖引入

本次实战基于现有cloud-order-consumer订单消费者服务接入Sentinel,统一适配当前工程版本,所有依赖版本由父工程统一管理,杜绝版本冲突。

8.2.1 订单服务引入Sentinel依赖

在cloud-order-consumer模块pom.xml中新增以下核心依赖:

xml 复制代码
<!-- SpringCloud Alibaba Sentinel 容错核心依赖 -->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>

<!-- Sentinel可视化控制台监控依赖 -->
<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-transport-simple-http</artifactId>
</dependency>

8.2.2 父工程新增版本管控

在父工程pom.xml的properties标签中,新增Spring Cloud Alibaba版本锁定,保证全工程版本统一、兼容Spring Cloud 2021.0.5:

xml 复制代码
<spring.cloud.alibaba.version>2021.0.5.0</spring.cloud.alibaba.version>

在dependencyManagement依赖管理中新增版本锁定:

xml 复制代码
<!-- SpringCloud Alibaba 全家桶版本锁定 -->
<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>

8.3 Sentinel 控制台部署与服务连接

Sentinel控制台是独立的可视化监控工具,用于实时查看服务状态、动态配置容错规则。

8.3.1 控制台启动

使用官方稳定版sentinel-dashboard-1.8.6.jar,启动命令:

plain 复制代码
java -jar sentinel-dashboard-1.8.6.jar --server.port=8858

启动完成后访问地址:http://localhost:8858,默认账号密码均为:sentinel

8.3.2 服务配置绑定控制台

在订单服务application.yml中新增Sentinel配置,实现服务注册到控制台、开启流量监控:

yaml 复制代码
# Sentinel容错组件配置
spring:
  cloud:
    sentinel:
      # 绑定Sentinel控制台地址
      transport:
        dashboard: localhost:8858
        # 客户端监控端口,默认随机,固定端口避免冲突
        port: 8719
      # 关闭Sentinel懒加载,服务启动即初始化
      eager: true

配置完成后重启订单服务,访问任意接口,即可在Sentinel控制台看到服务节点,代表接入成功。

8.4 全局异常兜底降级实战(代码级降级)

降级是指:接口出现异常、超时、报错时,不抛出系统异常,返回自定义友好兜底数据,避免前端报错、用户体验极差,同时防止异常扩散。我们基于OpenFeign远程调用接口实现全局降级兜底。

8.4.1 开启Feign整合Sentinel功能

在订单服务yml中开启Feign对Sentinel的支持(默认关闭):

yaml 复制代码
# 开启Feign整合Sentinel熔断降级
feign:
  sentinel:
    enabled: true

8.4.2 编写Feign接口降级实现类

创建降级兜底实现类,实现Feign远程调用接口,所有故障场景统一返回兜底数据:

java 复制代码
package com.cloud.order.fallback;

import com.cloud.common.result.Result;
import com.cloud.order.feign.UserFeignClient;
import org.springframework.stereotype.Component;

/**
 * 用户服务远程调用降级兜底实现类
 * 当远程服务超时、宕机、异常时,触发此类方法返回兜底数据
 */
@Component
public class UserFeignFallback implements UserFeignClient {

    /**
     * 用户查询接口降级兜底
     */
    @Override
    public Result<String> getUserInfo(Long userId) {
        return Result.error("用户服务暂时不可用,系统降级兜底,请稍后重试!用户ID:" + userId);
    }

    /**
     * 超时测试接口降级兜底
     */
    @Override
    public Result<String> testTimeout() {
        return Result.error("接口请求超时,触发Sentinel降级策略");
    }
}

8.4.3 绑定降级实现类到Feign接口

修改UserFeignClient接口,通过注解指定降级类:

java 复制代码
package com.cloud.order.feign;

import com.cloud.common.result.Result;
import com.cloud.order.fallback.UserFeignFallback;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

/**
 * 用户服务远程调用接口
 * fallback:指定降级兜底实现类
 */
@FeignClient(value = "cloud-user-provider", fallback = UserFeignFallback.class)
public interface UserFeignClient {

    @GetMapping("/user/get/{userId}")
    Result<String> getUserInfo(@PathVariable("userId") Long userId);

    @GetMapping("/user/timeout")
    Result<String> testTimeout();
}

8.4.4 降级效果测试

1、关闭用户服务提供者,模拟服务宕机故障;

2、调用订单Feign接口 /order/feign/create/1001

3、系统不再抛出超时、连接失败异常,直接返回自定义兜底提示,降级生效。

8.5 服务熔断实战(异常比例熔断、超时熔断)

熔断区别于降级:降级是被动兜底,熔断是主动切断故障调用。当接口异常率、超时率达到阈值,Sentinel会自动熔断接口,短时间内不再调用下游故障服务,避免服务雪崩,熔断窗口期结束后自动尝试恢复调用。

8.5.1 自定义测试熔断接口

在订单控制器新增模拟异常接口,用于测试熔断规则:

java 复制代码
package com.cloud.order.controller;

import com.cloud.common.result.Result;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Random;

@RestController
@RequestMapping("/order/sentinel")
public class SentinelTestController {

    // 随机数模拟接口异常
    private final Random random = new Random();

    /**
     * 模拟随机异常接口,用于测试异常熔断
     */
    @GetMapping("/error/test")
    public Result<String> testError() {
        // 50%概率抛出异常
        int num = random.nextInt(10);
        if (num > 5) {
            throw new RuntimeException("订单服务调用异常,模拟业务报错");
        }
        return Result.success("订单接口正常响应,业务执行成功");
    }

    /**
     * 模拟超时接口,用于测试超时熔断
     */
    @GetMapping("/time/out")
    public Result<String> testTimeOut() throws InterruptedException {
        // 模拟业务处理耗时1.5秒
        Thread.sleep(1500);
        return Result.success("接口执行完成");
    }
}

8.5.2 控制台配置熔断规则

登录Sentinel控制台,对 /order/sentinel/error/test 接口配置异常比例熔断规则

1、熔断策略:异常比例;

2、阈值比例:0.4(40%);

3、统计时长:1000毫秒;

4、熔断窗口期:5秒;

规则说明:1秒内接口异常率超过40%,立即熔断接口,5秒内所有请求直接走兜底,不再执行业务逻辑,5秒后半开尝试放行请求。

8.5.3 代码自定义熔断兜底

新增全局熔断异常处理器,拦截熔断状态,返回统一兜底数据:

java 复制代码
package com.cloud.order.handler;

import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.cloud.common.result.Result;

/**
 * Sentinel熔断、限流全局兜底处理器
 * 静态方法统一处理所有熔断限流异常
 */
public class SentinelBlockHandler {

    /**
     * 接口熔断兜底方法
     */
    public static Result<String> blockErrorHandler(BlockException e) {
        return Result.error("系统触发熔断机制,当前接口暂时停止服务,请稍后重试!");
    }

    /**
     * 接口限流兜底方法
     */
    public static Result<String> blockLimitHandler(BlockException e) {
        return Result.error("当前访问人数过多,触发流量限流,请稍后再试!");
    }
}

8.5.4 注解绑定熔断兜底规则

修改测试接口,添加Sentinel资源注解,绑定兜底方法:

java 复制代码
@SentinelResource(
        value = "testErrorResource", // 资源名称,控制台识别标识
        blockHandler = "blockErrorHandler", // 熔断兜底方法
        blockHandlerClass = SentinelBlockHandler.class // 兜底方法所在类
)
@GetMapping("/error/test")
public Result<String> testError() {
    int num = random.nextInt(10);
    if (num > 5) {
        throw new RuntimeException("订单服务调用异常,模拟业务报错");
    }
    return Result.success("订单接口正常响应,业务执行成功");
}

8.6 接口限流实战(QPS流量控制)

限流是预防服务雪崩的前置手段,通过限制接口每秒请求数(QPS)、并发线程数,保护服务不会被瞬间高并发流量打垮。本次实战实现QPS限流策略。

8.6.1 新增限流测试接口

java 复制代码
/**
 * 限流测试接口
 */
@SentinelResource(
        value = "limitTestResource",
        blockHandler = "blockLimitHandler",
        blockHandlerClass = SentinelBlockHandler.class
)
@GetMapping("/limit/test")
public Result<String> limitTest() {
    return Result.success("接口访问成功,正常处理请求");
}

8.6.2 控制台配置限流规则

1、资源名选择:limitTestResource;

2、限流阈值类型:QPS;

3、单机阈值:2(每秒最多2次请求);

4、流控模式:直接限流;

5、流控效果:快速失败。

连续快速刷新接口,超过2次/秒的请求会直接触发限流兜底,完美实现流量保护。

8.7 持久化规则配置(生产环境必备)

默认Sentinel规则保存在内存中,服务重启后规则全部丢失,生产环境必须配置Nacos持久化规则,保证规则永久生效、动态刷新。

8.7.1 引入持久化依赖

xml 复制代码
<!-- Sentinel规则Nacos持久化依赖 -->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-alibaba-sentinel-datasource-nacos</artifactId>
</dependency>

8.7.2 持久化配置

yaml 复制代码
spring:
  cloud:
    sentinel:
      datasource:
        # 限流规则持久化
        flow:
          nacos:
            server-addr: localhost:8848
            data-id: order-service-flow-rule
            group-id: DEFAULT_GROUP
            rule-type: flow
        # 熔断规则持久化
        degrade:
          nacos:
            server-addr: localhost:8848
            data-id: order-service-degrade-rule
            group-id: DEFAULT_GROUP
            rule-type: degrade

配置完成后,所有限流、熔断规则将存储在Nacos中,服务重启自动加载,解决规则丢失问题。

第九章 全套知识点终极总结与企业落地规范

9.1 微服务架构演进总结

单体架构、垂直架构、分布式架构、微服务架构四段迭代,核心解决的问题始终是:高并发、高可用、高扩展、易维护。微服务不是为了拆分而拆分,是业务体量发展后的必然架构升级。

9.2 Spring Cloud 核心组件实战总结

1、Eureka注册中心:实现服务自动注册、心跳续约、集群高可用、服务动态感知,是微服务治理基础;

2、LoadBalancer负载均衡:客户端本地流量分发,替代老旧Ribbon,实现多实例流量均衡,提升服务吞吐量;

3、OpenFeign远程调用:声明式接口调用,简化分布式通信代码,天然集成负载均衡,适配容错组件;

4、Sentinel容错组件:通过降级、熔断、限流三重防护,彻底解决服务雪崩问题,保障微服务集群稳定运行。

9.3 熔断、降级、限流核心区别(面试高频)

降级:服务正常、流量正常,主动放弃非核心业务,返回兜底数据,保障核心业务;

熔断:下游服务故障、异常率过高,主动切断调用,防止故障扩散;

限流:流量过大超出服务承载,限制请求数量,保护服务不被打垮。

9.4 企业生产环境落地强制规范

1、所有微服务必须集群部署,杜绝单点故障,注册中心必须搭建高可用集群;

2、所有远程Feign调用必须配置超时时间、降级兜底策略;

3、所有核心业务接口必须配置Sentinel限流、熔断规则,做好流量防护;

4、Sentinel规则必须配置Nacos持久化,避免服务重启规则丢失;

5、统一全局返回结果、统一异常处理、统一日志输出,方便线上问题排查;

6、禁止硬编码IP、端口调用服务,必须通过注册中心服务名调用。

相关推荐
Rust研习社1 小时前
组合真的优于继承吗?为什么 Rust 和 Go 都拥抱组合舍弃继承?
后端·rust·编程语言
IT_陈寒1 小时前
JavaScript的闭包把我坑惨了,说好的内存会自动回收呢?
前端·人工智能·后端
CaffeinePro2 小时前
Pydantic深度使用:数据校验、枚举、ORM映射
后端·fastapi
Chenyiax3 小时前
从 Chat 到 Responses:OpenAI API 抽象为什么变了?
后端
MariaH3 小时前
Koa和Express的区别
后端
MariaH3 小时前
Koa框架的使用
后端
luckdewei4 小时前
那个用 passlib 做认证的新同事,上线第一天就把用户密码写进了日志
后端
ping某5 小时前
为什么 Nginx 明明监听了 80,转发后端时却用了 4xxxx 端口?
后端·nginx
JustHappy5 小时前
我汇总了身边朋友的经历才发现,其实第一份实习是最难找的......
前端·后端·面试
uhakadotcom5 小时前
在python 的 工程化架构中 ,什么是 薄包装器层?
后端·面试·github