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、端口调用服务,必须通过注册中心服务名调用。