基于OpenFeign和Sentinel实现服务的请求限流、服务熔断和自动降级
0. 前提和准备
你已经使用openFeign实现了微服务之间的调用。
你会使用Jmeter进行压力测试,不会也没事,我这里有快速入门教学:
如何使用Jmeter对接口进行压力测试
1. Sentinel控制台的下载和安装
下载sentinel控制台的地址:
sentinel
在jar包的目录下,cmd输入以下运行命令:
1
| java -jar sentinel-dashboard-1.8.6.jar --server.port=8858 \
|
访问地址:
默认账号密码都是sentinel,进入首页:

2. 在服务中引入sentinel的依赖
例如:A服务要调用B服务的接口
则A服务的pom.xml文件加入sentinel的依赖:
1 2 3 4 5
| <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> </dependency>
|
如果还没有用到openfeign,则还要添加openFeign的依赖:
1 2 3 4
| <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency>
|
3. 配置Sentinel
在A服务(服务调用方)的bootstrap.yml(或者application.yml)配置文件中引入以下配置:
1 2 3 4 5 6 7 8 9 10 11 12
| spring: cloud: sentinel: transport: port: 8719 dashboard: localhost:8858
feign: sentinel: enabled: true
|
4. 使用Sentinel控制台
此时访问你要调用的远程接口。
例如,在swagger中访问以下接口:
1
| http://localhost:8084/aimin-admin/drug/category
|
然后再打开Sentinel控制台,刷新一下:

可以看到Sentinel开始监控我们的服务了。
5. 服务降级
5.1 在FeignClient接口上加入fallback,指向fallback实现类
1 2 3 4 5
| @FeignClient(name = "aimin-drug",path = "/aimin-drug",fallback = DrugFeignFallback.class) public interface DrugFeignClient { }
|
5.2 实现fallback类
我这边要实现的是DrugFeignFallback.java
因为DrugFeignFallback是DrugFeignClient接口的实现类,所以要重写所有的接口方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
| package com.oimc.aimin.admin.feign;
@Component public class DrugFeignFallback implements DrugFeignClient{
@Override public Result<?> insert(DrugRequest drug) { return Result.error("药品服务暂不可用(降级)"); }
@Override public Result<?> batchDelete(List<Integer> ids) { return Result.error("药品服务暂不可用(降级)"); }
@Override public Result<?> update(DrugRequest drug) { return Result.error("药品服务暂不可用(降级)"); }
@Override public Result<?> getById(String id) { return Result.error("药品服务暂不可用(降级)"); }
@Override public Result<?> drugList() { return Result.error("药品服务暂不可用(降级)"); }
@Override public Result<?> page(PageDrugRequest page) { return Result.error("药品服务暂不可用(降级)"); }
@Override public Result<?> categoryTree(Integer id) { return Result.error("药品服务暂不可用(降级)"); }
@Override public Result<?> categoryList() { return Result.error("药品服务暂不可用(降级)"); }
@Override public Result<?> insertCategory(DrugCategoryRequest request) { return Result.error("药品服务暂不可用(降级)"); }
@Override public Result<?> updateCategory(Integer id, DrugCategoryRequest request) { return Result.error("药品服务暂不可用(降级)"); }
@Override public Result<?> deleteCategory(Integer id) { return Result.error("药品服务暂不可用(降级)"); }
@Override public Result<?> batchUpload(@RequestPart List<MultipartFile> files) { return Result.error("药品上传服务暂不可用(降级)"); }
@Override public Result<Boolean> setMainImage(Integer imageId) { return Result.error("图片设置失败,药品服务不可用(降级)"); }
@Override public Result<?> getById(Integer imageId) { return Result.error("图片查询失败,药品服务不可用(降级)"); }
@Override public Result<?> listByDrugId(Integer drugId) { return Result.error("药品图片列表服务暂不可用(降级)"); }
@Override public Result<Boolean> deleteImage(Integer imageId) { return Result.error("图片删除失败,药品服务不可用(降级)"); }
@Override public void deleteImageByPath(String path) { System.err.println("药品服务不可用,无法删除图片路径!"); }
}
|
5.3 测试
正常情况下
启动admin微服务和Drug微服务
调用查询药品信息的接口:

关闭被调用的服务Drug微服务,再次在swagger中调用查询药品信息的接口,出现降级的信息:

6. 请求限流
在Sentinel控制台中添加流控规则:


每秒只能请求5次

使用Jmeter进行压力测试:

Jmeter配置:
- 线程数:100
- Ramp-up:1 秒
- Loop:1 次
表示 100个用户在1秒内全部启动,每个用户发送1次请求。
测试结果:

100个请求只成功了一个
7. 服务熔断



该熔断配置的含义是:
当1秒内收到至少5个请求,其中超过50%的请求响应超过200ms时,该接口将进入20秒的熔断状态。
然后使用Jmeter进行压力测试即可,我这里就不演示了…..
微服务会进入20s的熔断状态,也就是任何请求都不会再接收。
8. 线程隔离(具体过程就不演示了)
Sentinel使用并发线程数限流(Thread Count Limit)来实现类似线程隔离的效果。
参考资料
可以参考白马的SpringCloud资料
END