Spring Cloud Alibaba Sentinel 整合 Feign:限流熔断与自定义降级实战
<|begin▁of▁sentence|># 1. 概述
本文分享 **Spring Cloud Alibaba 之 Sentinel 与 Feign 的整合**。Sentinel 提供了 `feign-sentinel` 的整合模块,提供 Feign 调用的限流、熔断等功能。
> 另外,在早期 Sentinel 还未提供 `feign-sentinel` 整合模块时,Spring Cloud Alibaba 通过自定义的 [SentinelInvocationHandler](https://github.com/alibaba/spring-cloud-alibaba/blob/2.2.x/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/feign/SentinelInvocationHandler.java) ,实现了对 Feign 调用的限流、熔断等功能。目前,该方式已经**废弃**,使用 Sentinel 提供的方案。
# 2. 快速入门
> 示例代码对应仓库:
>
> - 服务提供者:`labx-10-sc-sentinel-demo01-provider`
> - 服务消费者:`labx-10-sc-sentinel-feign-demo01-consumer`
本小节,我们会在服务消费者中,使用 Feign 调用服务提供者提供的 HTTP 接口。同时,我们会使用 Sentinel 对该 Feign 调用进行限流。
## 2.1 服务提供者
创建服务提供者 `labx-10-sc-sentinel-demo01-provider` 项目,提供服务 HTTP 接口。代码比较简单,如下:
- 创建 [ProviderController](https://github.com/YunaiV/SpringBoot-Labs/blob/master/labx-10-spring-cloud-alibaba-sentinel/labx-10-sc-sentinel-demo01-provider/src/main/java/cn/iocoder/springcloudalibaba/labx10/sentineldemo/providerdemo/controller/ProviderController.java) 类,提供 `/demo/echo` 接口。
## 2.2 服务消费者
创建服务消费者 `labx-10-sc-sentinel-feign-demo01-consumer` 项目,使用 Feign 调用服务提供者的 HTTP 接口。
### 2.2.1 引入依赖
创建 [`pom.xml`](https://github.com/YunaiV/SpringBoot-Labs/blob/master/labx-10-spring-cloud-alibaba-sentinel/labx-10-sc-sentinel-feign-demo01-consumer/pom.xml) 文件中,引入相关依赖。
```xml
labx-10
cn.iocoder.springboot.labs
1.0-SNAPSHOT
4.0.0
labx-10-sc-sentinel-feign-demo01-consumer
2.2.4.RELEASE
Hoxton.SR1
2.2.0.RELEASE
org.springframework.boot
spring-boot-dependencies
${spring.boot.version}
pom
import
org.springframework.cloud
spring-cloud-dependencies
${spring.cloud.version}
pom
import
com.alibaba.cloud
spring-cloud-alibaba-dependencies
${spring.cloud.alibaba.version}
pom
import
org.springframework.boot
spring-boot-starter-web
com.alibaba.cloud
spring-cloud-starter-alibaba-sentinel
org.springframework.cloud
spring-cloud-starter-openfeign
com.alibaba.cloud
spring-cloud-alibaba-sentinel-feign
```
重点引入 `spring-cloud-alibaba-sentinel-feign` 依赖,实现对 Sentinel 对 Feign 的整合。
### 2.2.2 配置文件
创建 [`application.yaml`](https://github.com/YunaiV/SpringBoot-Labs/blob/master/labx-10-spring-cloud-alibaba-sentinel/labx-10-sc-sentinel-feign-demo01-consumer/src/main/resources/application.yaml) 配置文件,添加相关配置。
```yaml
server:
port: 8081
spring:
application:
name: demo-consumer
cloud:
# Sentinel 配置
sentinel:
# 控制台地址
transport:
dashboard: 192.168.3.196:7070
# 服务提供者的配置
provider:
service:
url: http://127.0.0.1:8080
# Feign 配置
feign:
# Sentinel 配置
sentinel:
enabled: true # 开启 Feign 对 Sentinel 的支持
```
**重点**是 `feign.sentinel.enabled` 配置项,设置为 `true`,开启 Feign 对 Sentinel 的支持。
### 2.2.3 ProviderService
创建 [ProviderService](https://github.com/YunaiV/SpringBoot-Labs/blob/master/labx-10-spring-cloud-alibaba-sentinel/labx-10-sc-sentinel-feign-demo01-consumer/src/main/java/cn/iocoder/springcloudalibaba/labx10/sentineldemo/consumerdemo/service/ProviderService.java) 接口,作为 Feign 声明式调用接口。代码如下:
```java
@FeignClient(name = "demo-provider", url = "${provider.service.url}")
public interface ProviderService {
@GetMapping("/demo/echo")
String echo();
}
```
- 通过 `@FeignClient` 注解,声明一个 Feign 客户端,其中 `name` 为服务名,`url` 指向服务提供者的地址。
### 2.2.4 ConsumerController
创建 [ConsumerController](https://github.com/YunaiV/SpringBoot-Labs/blob/master/labx-10-spring-cloud-alibaba-sentinel/labx-10-sc-sentinel-feign-demo01-consumer/src/main/java/cn/iocoder/springcloudalibaba/labx10/sentineldemo/consumerdemo/controller/ConsumerController.java) 类,提供使用 Feign 声明式调用服务的 HTTP 接口。代码如下:
```java
@RestController
public class ConsumerController {
@Autowired
private ProviderService providerService;
@GetMapping("/feign_echo")
public String feignEcho() {
return providerService.echo();
}
}
```
### 2.2.5 DemoConsumerApplication
创建 [DemoConsumerApplication](https://github.com/YunaiV/SpringBoot-Labs/blob/master/labx-10-spring-cloud-alibaba-sentinel/labx-10-sc-sentinel-feign-demo01-consumer/src/main/java/cn/iocoder/springcloudalibaba/labx10/sentineldemo/consumerdemo/DemoConsumerApplication.java) 类,作为应用启动类。代码如下:
```java
@SpringBootApplication
@EnableFeignClients
public class DemoConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(DemoConsumerApplication.class, args);
}
}
```
## 2.3 简单测试
① 首先,启动服务提供者 `labx-10-sc-sentinel-demo01-provider` 项目。
② 然后,启动服务消费者 `labx-10-sc-sentinel-feign-demo01-consumer` 项目。
③ 最后,访问服务消费者的 http://127.0.0.1:8081/feign_echo 接口,保证 Feign 调用是成功的。返回结果如下:
```
echo:172.16.88.183:8080
```
此时,我们打开 Sentinel 控制台,可以看到 Feign 调用对应的**资源名**为 `GET:http://127.0.0.1:8080/demo/echo`。如下图所示:
并且,此时该资源的**实时监控**如下:
④ 给 `GET:http://127.0.0.1:8080/demo/echo` 资源设置一个每秒 1 次的限流规则。如下图所示:
然后,我们快速访问 http://127.0.0.1:8081/feign_echo 接口,会看到被限流的错误提示。返回结果如下:
```
Blocked by Sentinel (flow limiting)
```
并且,此时该资源的**实时监控**如下:
# 3. 整合说明
> 友情提示:本小节为选读,不感兴趣的同学可以跳过。
在 `feign-sentinel` 的整合模块中,Sentinel 自定义了 [SentinelFeign](https://github.com/alibaba/Sentinel/blob/master/sentinel-adapter/sentinel-feign-adapter/src/main/java/com/alibaba/cloud/sentinel/feign/SentinelFeign.java) 类,通过 [Feign 的 Builder 模式](https://www.iocoder.cn/Spring-Cloud/Feign/?self),创建了具有 Sentinel 功能的 Feign 客户端。
SentinelFeign 的创建代码如下:
```java
// SentinelFeign.java
public final class SentinelFeign {
public static Builder builder() {
return new Builder();
}
public static final class Builder extends Feign.Builder {
// ... 省略中间代码
@Override
public Feign build() {
super.invocationHandlerFactory(new InvocationHandlerFactory() {
@Override
public InvocationHandler create(Target target, Map dispatch) {
// 创建「SentinelInvocationHandler」对象,并将 dispatch 包装成具有 Sentinel 功能的 MethodHandler 映射
return new SentinelInvocationHandler(target, dispatch);
}
});
// 设置 Contract 为 SentinelContractHolder,用于创建具有 Sentinel 功能的 MethodHandler
super.contract(new SentinelContractHolder(contract));
return super.build();
}
}
}
```
- 通过创建 [SentinelInvocationHandler](https://github.com/alibaba/Sentinel/blob/master/sentinel-adapter/sentinel-feign-adapter/src/main/java/com/alibaba/cloud/sentinel/feign/SentinelInvocationHandler.java) 类,作为 Feign 调用的 InvocationHandler 处理器。这样,每次 Feign 调用,都会触发 `SentinelInvocationHandler#invoke(...)` 方法,从而调用 Sentinel 的 API,实现限流、熔断等功能。
- 通过创建 [SentinelContractHolder](https://github.com/alibaba/Sentinel/blob/master/sentinel-adapter/sentinel-feign-adapter/src/main/java/com/alibaba/cloud/sentinel/feign/SentinelContractHolder.java) 类,在创建 Feign 调用的 MethodHandler 时,包装成具有 Sentinel 功能的 [SentinelMethodHandler](https://github.com/alibaba/Sentinel/blob/master/sentinel-adapter/sentinel-feign-adapter/src/main/java/com/alibaba/cloud/sentinel/feign/SentinelMethodHandler.java) 类。
# 4. 自定义 Fallback
> 示例代码对应仓库:
>
> - 服务提供者:`labx-10-sc-sentinel-demo01-provider`
> - 服务消费者:`labx-10-sc-sentinel-feign-demo02-consumer`
在 Sentinel 与 Feign 的整合中,我们可以通过定义 [Fallback](https://github.com/OpenFeign/feign/wiki/Custom-error-handling#fallback) 类,在 Feign 调用被限流、熔断时,返回 Fallback 处理结果,实现**服务降级**的效果。
本小节,我们会在[「2. 快速入门」](https://www.iocoder.cn/Spring-Cloud-Alibaba/Sentinel/Feign/?self#)的小节的基础上,进行 Fallback 功能的演示。
## 4.1 服务消费者
创建服务消费者 `labx-10-sc-sentinel-feign-demo02-consumer` 项目,使用 Feign 调用服务提供者的 HTTP 接口。
### 4.1.1 引入依赖
和[「2.2.1 引入依赖」](https://www.iocoder.cn/Spring-Cloud-Alibaba/Sentinel/Feign/?self#)一致,见 [`pom.xml`](https://github.com/YunaiV/SpringBoot-Labs/blob/master/labx-10-spring-cloud-alibaba-sentinel/labx-10-sc-sentinel-feign-demo02-consumer/pom.xml) 文件。
### 4.1.2 配置文件
和[「2.2.2 配置文件」](https://www.iocoder.cn/Spring-Cloud-Alibaba/Sentinel/Feign/?self#)一致,见 [`application.yaml`](https://github.com/YunaiV/SpringBoot-Labs/blob/master/labx-10-spring-cloud-alibaba-sentinel/labx-10-sc-sentinel-feign-demo02-consumer/src/main/resources/application.yaml) 文件。
### 4.1.3 ProviderService
修改 [ProviderService](https://github.com/YunaiV/SpringBoot-Labs/blob/master/labx-10-spring-cloud-alibaba-sentinel/labx-10-sc-sentinel-feign-demo02-consumer/src/main/java/cn/iocoder/springcloudalibaba/labx10/sentineldemo/consumerdemo/service/ProviderService.java) 接口,增加 `fallback` 配置项,设置 Fallback 处理类为 ProviderServiceFallback。代码如下:
```java
@FeignClient(name = "demo-provider", url = "${provider.service.url}",
fallback = ProviderServiceFallback.class)
public interface ProviderService {
@GetMapping("/demo/echo")
String echo();
}
```
创建 [ProviderServiceFallback](https://github.com/YunaiV/SpringBoot-Labs/blob/master/labx-10-spring-cloud-alibaba-sentinel/labx-10-sc-sentinel-feign-demo02-consumer/src/main/java/cn/iocoder/springcloudalibaba/labx10/sentineldemo/consumerdemo/service/ProviderServiceFallback.java) 类,实现 ProviderService 接口,作为 Fallback 处理类。代码如下:
```java
@Component
public class ProviderServiceFallback implements ProviderService {
@Override
public String echo() {
return "fallback";
}
}
```
### 4.1.4 ConsumerController
和[「2.2.4 ConsumerController」](https://www.iocoder.cn/Spring-Cloud-Alibaba/Sentinel/Feign/?self#)一致,见 [ConsumerController](https://github.com/YunaiV/SpringBoot-Labs/blob/master/labx-10-spring-cloud-alibaba-sentinel/labx-10-sc-sentinel-feign-demo02-consumer/src/main/java/cn/iocoder/springcloudalibaba/labx10/sentineldemo/consumerdemo/controller/ConsumerController.java) 类。
### 4.1.5 DemoConsumerApplication
和[「2.2.5 DemoConsumerApplication」](https://www.iocoder.cn/Spring-Cloud-Alibaba/Sentinel/Feign/?self#)一致,见 [DemoConsumerApplication](https://github.com/YunaiV/SpringBoot-Labs/blob/master/labx-10-spring-cloud-alibaba-sentinel/labx-10-sc-sentinel-feign-demo02-consumer/src/main/java/cn/iocoder/springcloudalibaba/labx10/sentineldemo/consumerdemo/DemoConsumerApplication.java) 类。
## 4.2 简单测试
① 首先,启动服务提供者 `labx-10-sc-sentinel-demo01-provider` 项目。
② 然后,启动服务消费者 `labx-10-sc-sentinel-feign-demo02-consumer` 项目。
③ 最后,访问服务消费者的 http://127.0.0.1:8081/feign_echo 接口,保证 Feign 调用是成功的。
④ 给 `GET:http://127.0.0.1:8080/demo/echo` 资源设置一个每秒 1 次的限流规则。
然后,我们快速
最新文章
- 电动化浪潮席卷全球,智能驾驶与车联网重塑未来出行
- NVH静音工程解析:关键技术与发展趋势
- 发动机性能提升汽车动力输出效率
- 电动汽车革命:从技术突破到未来出行新生态
- 固态电池突破:高能量密度与硫化物电解质技术解析
- 三角警示牌与车身框架:现代汽车安全设计全解析
- 斯柯达汽车品质与创新之路
- Go语言基础:变量、常量与流程控制详解
- 汽车冷却系统水泵故障导致发动机过热
- **镀晶剐蹭事故处理指南:从现场到修复全流程**
- 智能驾驶与充电网络:未来出行的三大技术变革
- 汽车清洁保养小技巧分享
- 电动化浪潮下:电池技术突破与自动驾驶未来展望
- 《排气管与轮毂尺寸匹配指南:改装必知的黄金法则》
- 自动驾驶技术发展现状、挑战与未来趋势分析
- 车路协同:让汽车与道路对话的智能驾驶新时代
- 宝马驾驶体验无与伦比的舒适
- 高效能发动机提升汽车动力性能
- 雷达技术助力智能汽车发展
- 激光雷达与高精地图:L4自动驾驶核心技术解析
