Sentinel学习
什么是服务雪崩
在微服务架构中,根据业务来拆分成一个个的服务,服务与服务之间可以通过 RPC
相互调用,在 Spring Cloud 中可以用 RestTemplate + LoadBalanceClient
和 Feign
来调用。为了保证其高可用,单个服务通常会集群部署。由于网络原因或者自身的原因,服务并不能保证 100% 可用,如果单个服务出现问题,调用这个服务就会出现线程阻塞,此时若有大量的请求涌入,Servlet
容器的线程资源会被消耗完毕,导致服务瘫痪。服务与服务之间的依赖性,故障会传播,会对整个微服务系统造成灾难性的严重后果,这就是服务故障的 “雪崩” 效应。
为了解决这个问题,业界提出了熔断器模型。
阿里巴巴开源了 Sentinel 组件,实现了熔断器模式,Spring Cloud 对这一组件进行了整合。在微服务架构中,一个请求需要调用多个服务是非常常见的,如下图:
较底层的服务如果出现故障,会导致连锁故障。当对特定的服务的调用的不可用达到一个阀值熔断器将会被打开。
熔断器打开后,为了避免连锁故障,通过 fallback
方法可以直接返回一个固定值
什么是Sentinel
Sentinel 是面向分布式服务架构的高可用流量防护组件,主要以流量为切入点,从限流、流量整形、熔断降级、系统负载保护、热点防护等多个维度来帮助开发者保障微服务的稳定性。
Sentinel 具有以下特性:
- 丰富的应用场景:Sentinel 承接了阿里巴巴近 10 年的双十一大促流量的核心场景,例如秒杀(即突发流量控制在系统容量可以承受的范围)、消息削峰填谷、集群流量控制、实时熔断下游不可用应用等。
- 完备的实时监控:Sentinel 同时提供实时的监控功能。您可以在控制台中看到接入应用的单台机器秒级数据,甚至 500 台以下规模的集群的汇总运行情况。
- 广泛的开源生态:Sentinel 提供开箱即用的与其它开源框架/库的整合模块,例如与 Spring Cloud、Dubbo、gRPC 的整合。您只需要引入相应的依赖并进行简单的配置即可快速地接入 Sentinel。
- 完善的 SPI 扩展点:Sentinel 提供简单易用、完善的 SPI 扩展接口。您可以通过实现扩展接口来快速地定制逻辑。例如定制规则管理、适配动态数据源等。
Feign 中使用 Sentinel
如果要在您的项目中引入 Sentinel,使用 group ID 为 org.springframework.cloud
和 artifact ID 为 spring-cloud-starter-alibaba-sentinel
的 starter。
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
Sentinel 适配了 Feign 组件。但默认是关闭的。需要在配置文件中配置打开它,在配置文件增加以下代码:
feign:
sentinel:
enabled: true
在 Service 中增加 fallback 指定类
package com.funtl.hello.spring.cloud.alibaba.nacos.consumer.feign.service;
import com.funtl.hello.spring.cloud.alibaba.nacos.consumer.feign.service.fallback.EchoServiceFallback;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
@FeignClient(value = "nacos-provider", fallback = EchoServiceFallback.class)
public interface EchoService {
@GetMapping(value = "/echo/{message}")
String echo(@PathVariable("message") String message);
}
创建熔断器类并实现对应的 Feign 接口
package com.funtl.hello.spring.cloud.alibaba.nacos.consumer.feign.service.fallback;
import com.funtl.hello.spring.cloud.alibaba.nacos.consumer.feign.service.EchoService;
import org.springframework.stereotype.Component;
@Component
public class EchoServiceFallback implements EchoService {
@Override
public String echo(String message) {
return "echo fallback";
}
}
测试熔断器
此时我们关闭服务提供者,再次请求 http://localhost:9092/echo/hi 浏览器会显示:
echo fallback
核心概念
sentinel
的使用可以分为两个部分
核心库不依赖任何框架/库,能够允许在jdk7
以上的版本运行时环境,同时对Dubbo、SpringCloud等框架也有比较好的支持。
控制台主要负责管理推送规则、监控、集群限流分配管理、机器发现等。1f7c2a561e9f43068789f687766b2997
下载方式
注意:启动 Sentinel 控制台需要 JDK 版本为 1.8 及以上版本。
- Windows平台安装包下载
可以从https://github.com/alibaba/Sentinel/releases
下载sentinel-dashboard-$version.jar
包。
使用如下命令启动控制台:
java -Dserver.port=8718 -Dcsp.sentinel.dashboard.server=localhost:8718 -Dproject.name=sentinel-dashboard -Dcsp.sentinel.api.port=8719 -jar D:\sentinel\sentinel-dashboard-1.8.0.jar
1
其中-Dserver.port=8718
用于指定Sentinel
控制台端口为8718
,F:\software\sentinel\sentinel-dashboard-1.8.0.jar
为下载的包路径地址。
- 打开控制台
Sentinel
提供了一个可视化的操作平台,安装好之后,在浏览器中输入(http://localhost:8718 (opens new window))就可以访问了,默认的用户名和密码都是sentinel
(我使用的是1.8.0版本)
如何使用
1、添加依赖
<!-- springcloud alibaba sentinel -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<!-- SpringBoot Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
2、添加Sentinel配置
spring:
cloud:
sentinel:
# 取消控制台懒加载
eager: true
port: 8719
transport:
# 控制台地址
dashboard: 127.0.0.1:8071
3、添加TestUserController.java
,模拟接口返回用户信息。
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TestUserController
{
@GetMapping("/user/info")
public Object info()
{
return "{\"username\":\"admin\",\"password\":\"admin123\"}";
}
}
4、增加Feign调用,来查看当Feign请求出现故障或者熔断的时候,如何通过熔断器进行返回
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TestUserController
{
@RequestMapping("/sout")
public Object test() {
AjaxResult admin = systemService.getUserByUsername("admin");
logger.debug(admin.toString());
logger.debug(userNmae);
return admin;
}
}
5、新增SystemService.java
import com.ruoyi.common.core.constant.ServiceNameConstants;
import com.ruoyi.common.core.web.domain.AjaxResult;
import com.ruoyi.test.service.fallback.DefaultFeginFallback;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
/**
* @author :suiquantong
* @date : 2021/9/25 16:23
* @description : 描述
*
*contextId = "systemService" 不想将同一服务所有的接口放到一个service 是可以这样写
*value = ServiceNameConstants.SYSTEM_SERVICE 服务的名称 nacos 里的服务名称
*fallbackFactory = DefaultFeginFallback.class 出现错误的时候 进行fallback 熔断返回
*configuration = FeignConfiguration.class 自定义Feign配置
*
*
*/
@FeignClient(contextId = "systemService", value = ServiceNameConstants.SYSTEM_SERVICE, fallbackFactory = DefaultFeginFallback.class,configuration = FeignConfiguration.class)
public interface SystemService {
@RequestMapping(value = "/user/getUserByUsername/{username}",method = RequestMethod.GET)
AjaxResult getUserByUsername(@PathVariable("username") String username);
}
6、 新建DefaultFeginFallback.java 配置熔断内容
import com.ruoyi.common.core.web.domain.AjaxResult;
import com.ruoyi.test.service.SystemService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.openfeign.FallbackFactory;
import org.springframework.stereotype.Component;
/**
* @author :suiquantong
* @date : 2021/9/25 17:25
* @description : 用户服务发生熔断的返回
*/
@Component
public class DefaultFeginFallback implements FallbackFactory<SystemService> {
private static final Logger log = LoggerFactory.getLogger(DefaultFeginFallback.class);
@Override
public SystemService create(Throwable throwable) {
log.error("用户服务调用失败:{}", throwable.getMessage());
return new SystemService() {
@Override
public AjaxResult getUserByUsername(String username) {
return AjaxResult.error("服务宕机了,请联系管理员");
}
};
}
}
通过使用熔断器 可以在我们的Sentinel控制台上看到熔断的情况还有通过QPS,拒绝QPS 和响应时间
7、在Application
启动类加入注解@SpringBootApplication
。
@SpringBootApplication
public class RuoYiXxxxApplication
{
public static void main(String[] args)
{
SpringApplication.run(RuoYiXxxxApplication.class, args);
System.out.println("(♥◠‿◠)ノ゙ Xxxx启动成功 ლ(´ڡ`ლ)゙ \n" +
" .-------. ____ __ \n" +
" | _ _ \\ \\ \\ / / \n" +
" | ( ' ) | \\ _. / ' \n" +
" |(_ o _) / _( )_ .' \n" +
" | (_,_).' __ ___(_ o _)' \n" +
" | |\\ \\ | || |(_,_)' \n" +
" | | \\ `' /| `-' / \n" +
" | | \\ / \\ / \n" +
" ''-' `'-' `-..-' ");
}
}
8、启动服务,查看Sentinel
控制台的请求数据
Sentinel在RuoYi中的使用主要是在网关中 对所有的进入接口进行 拦截 判断路径 熔断的接口进行提示
定义资源
资源是Sentinel
中的核心概念之一。我们说的资源,可以是任何东西,服务,服务里的方法,甚至是一段代码。最常用的资源是我们代码中的Java方法。Sentinel
提供了@SentinelResource
注解用于定义资源,并提供了AspectJ
的扩展用于自动定义资源、处理BlockException
等。
官网文档:https://github.com/alibaba/Sentinel/wiki/如何使用#定义资源
代码定义
@SentinelResource
用于定义资源,并提供可选的异常处理和fallback
配置项。
接口定义IUserService.java
/**
* 用户接口
*
* @author ruoyi
*/
public interface IUserService
{
public Object selectUserByName(String username);
}
接口实现IUserServiceImpl.java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
/**
* 用户实现
*
* @author ruoyi
*/
@Service
public class IUserServiceImpl implements IUserService
{
@Autowired
private RestTemplate restTemplate;
@Bean
public RestTemplate restTemplate()
{
return new RestTemplate();
}
@SentinelResource(value = "selectUserByName", blockHandler = "selectUserByNameBlockHandler", fallback = "selectUserByNameFallback")
@Override
public Object selectUserByName(String username)
{
return restTemplate.getForObject("http://localhost:9201/user/info/" + username, String.class);
}
// 服务流量控制处理,参数最后多一个 BlockException,其余与原函数一致。
public Object selectUserByNameBlockHandler(String username, BlockException ex)
{
System.out.println("selectUserByNameBlockHandler异常信息:" + ex.getMessage());
return "{\"code\":\"500\",\"msg\": \"" + username + "服务流量控制处理\"}";
}
// 服务熔断降级处理,函数签名与原函数一致或加一个 Throwable 类型的参数
public Object selectUserByNameFallback(String username, Throwable throwable)
{
System.out.println("selectUserByNameFallback异常信息:" + throwable.getMessage());
return "{\"code\":\"500\",\"msg\": \"" + username + "服务熔断降级处理\"}";
}
}
测试接口请求TestUserController.java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TestUserController
{
@Autowired
private IUserService userService;
@GetMapping("/info/{username}")
public Object info(@PathVariable("username") String username)
{
return userService.selectUserByName(username);
}
}
属性说明
@SentinelResource
注解包含以下属性:
参数 | 描述 |
---|---|
value | 资源名称,必需项(不能为空) |
entryType | 资源调用方向,可选项(默认为EntryType.OUT ) |
resourceType | 资源的分类 |
blockHandler | 对应处理BlockException 的函数名称 |
blockHandlerClass | 处理类的Class 对象,函数必需为static 函数 |
fallback | 用于在抛出异常的时候提供fallback 处理逻辑 |
defaultFallback | 用作默认的回退的方法 |
fallbackClass | 异常类的Class 对象,函数必需为static 函数 |
exceptionsToTrace | 异常类跟踪列表(默认为Throwable.class) |
exceptionsToIgnore | 排除掉的异常类型 |
提示
注意:注解方式埋点不支持 private 方法。
我们可以通过对某个资源进行QPS 限制和 并发线程数限制 设置阈值
流量规则
控制台定义
选择流控规则
,新增流控规则,填入对应信息。
-
资源名: 唯一名称,默认请求路径
-
针对来源: Sentinel可以针对调用者进行限流,填写微服务名,默认default(不区分来源)
-
阈值类型/单机阈值:
- QPS(每秒请求数量):当调用该api的QPS达到阈值的时候,进行限流
- 线程数:当调用该api的线程数达到阈值的时候,进行限流
-
是否集群: 不需要集群
-
流控模式:
- 直接:api达到限流条件时,直接限流
- 关联:当关联的资源达到限流阈值时,就限流自己
- 链路:只记录指定链路上的流量(指定资源从入口资源进来的流量,如果达到峰值,就进行限流)【api级别的针对来源】
-
流控效果:
- 快速失败:直接失败,抛异常
- Warm Up:根据coldFactor(冷加载因子,默认3)的值,从阈值/coldFactor,经过预热时长,才达到设置的QPS阈值
- 排队等待:匀速排队,让请求以匀速通过,阈值类型必须设置为QPS,否则无效
代码定义
理解上面规则的定义之后,我们可以通过调用FlowRuleManager.loadRules()
方法来用硬编码的方式定义流量控制规则,比如:
private void initFlowQpsRule() {
List<FlowRule> rules = new ArrayList<>();
FlowRule rule = new FlowRule(resourceName);
// set limit qps to 20
rule.setCount(20);
rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
rule.setLimitApp("default");
rules.add(rule);
FlowRuleManager.loadRules(rules);
}
属性说明
流量控制规则(FlowRule
)重要属性
参数 | 描述 | 描述 |
---|---|---|
resource | 资源名,资源名是限流规则的作用对象 | |
limitApp | 流控针对的调用来源,若为 default 则不区分调用来源 | default,代表不区分调用来源 |
grade | 限流阈值类型,QPS 模式(1)或并发线程数模式(0) | QPS 模式 |
count | 限流阈值 | |
strategy | 调用关系限流策略:直接、链路、关联 | 根据资源本身(直接) |
controlBehavior | 流量控制效果(直接拒绝、Warm Up、匀速排队) | 直接拒绝 |
clusterMode | 是否集群限流 | 否 |
同一个资源可以同时有多个限流规则,检查规则时会依次检查。
提示
从1.6.3
版本开始,Sentinel Web filter
默认收敛所有URL
的入口context
,因此链路限流不生效。1.7.0
版本开始(对应SCA 2.1.1.RELEASE
),我们在CommonFilter
引入了WEB_CONTEXT_UNIFY
这个init parameter
,用于控制是否收敛context
。将其配置为false
即可根据不同的URL
进行链路限流。 参考:https://github.com/alibaba/sentinel/issues/1213
降级规则降级规则
现代微服务架构都是分布式的,由非常多的服务组成。不同服务之间相互调用,组成复杂的调用链路。以上的问题在链路调用中会产生放大的效果。复杂链路上的某一环不稳定,就可能会层层级联,最终导致整个链路都不可用。因此我们需要对不稳定的弱依赖服务调用进行熔断降级,暂时切断不稳定调用,避免局部不稳定因素导致整体的雪崩。熔断降级作为保护自身的手段,通常在客户端(调用端)进行配置。
控制台定义
选择降级规则
,新增降级规则,填入对应信息。
代码定义
private void initDegradeRule() {
List<DegradeRule> rules = new ArrayList<>();
DegradeRule rule = new DegradeRule();
rule.setResource(KEY);
// set threshold RT, 10 ms
rule.setCount(10);
rule.setGrade(RuleConstant.DEGRADE_GRADE_RT);
rule.setTimeWindow(10);
rules.add(rule);
DegradeRuleManager.loadRules(rules);
}
属性说明
熔断降级规则(DegradeRule
)重要属性
参数 | 描述 | 描述 |
---|---|---|
resource | 资源名,即规则的作用对象 | |
grade | 熔断策略,支持慢调用比例/异常比例/异常数策略 | 慢调用比例 |
count | 慢调用比例模式下为慢调用临界 RT(超出该值计为慢调用);异常比例/异常数模式下为对应的阈值 | |
timeWindow | 熔断时长,单位为 s | |
minRequestAmount | 熔断触发的最小请求数,请求数小于该值时即使异常比率超出阈值也不会熔断(1.7.0 引入) | 5 |
statIntervalMs | 统计时长(单位为 ms),如 60*1000 代表分钟级(1.8.0 引入) | 1000 ms |
slowRatioThreshold | 慢调用比例阈值,仅慢调用比例模式有效(1.8.0 引入) |
同一个资源可以同时有多个降级规则。
对某个资源设置熔断后 当熔断的异常数量足够多,在接下来的时间内都会走熔断器 这样可以减少故障节点的访问次数
动态配置规则
上面的规则配置,都是存在内存中的。即如果应用重启,这个规则就会失效,可以整合动态配置系统,如ZooKeeper
、Nacos
、Apollo
等,动态地实时刷新配置规则。
文件配置规则
Sentinel
支持通过本地文件加载规则配置,使用方式如下(限流规则作为演示)
spring:
cloud:
sentinel:
datasource:
ds1:
file:
file: classpath:flowRule.json
data-type: json
rule-type: flow
flowRule.json
对应com.alibaba.csp.sentinel.slots.block.flow.FlowRule
各属性。
[
{
"resource": "selectUserByName",
"count": 1,
"grade": 1,
"limitApp": "default",
"strategy": 0,
"controlBehavior": 0
}
]
Nacos配置规则
当sentinel
重新启动时,sentinel dashboard
中原来的数据将会全部消失,这样就需要重新定义限流规则,无疑是不可取的。所以需要将sentinel
中定义的限流规则保存到配置中心里面。
具体的实现方法如下:
1、在nacos中定义自定义限流策略sentinel-ruoyi-xxxx
[
{
"resource": "selectUserByName", //熔断资源名称
"count": 2, //限流阈值
"grade": 1, //限流阈值类型,QPS 模式(1)或并发线程数模式(0)
"limitApp": "default", //流控针对的调用来源,若为 default 则不区分调用来源
"strategy": 0, //调用关系限流策略:直接、链路、关联
"controlBehavior": 0 //流量控制效果(直接拒绝、Warm Up、匀速排队)
}
]
2、添加依赖
<!-- springcloud alibaba nacos config -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!-- sentinel datasource nacos -->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
3、添加相关配置,sentinel
下面的dataSource
中配置nacos
#配置在Gateway模块下的 bootstrap.yml 里面
spring:
application:
# 应用名称
name: ruoyi-xxxx
cloud:
nacos:
config:
# 配置中心地址
server-addr: 127.0.0.1:8848
# 配置文件格式
file-extension: yml
# 共享配置
shared-configs:
- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
sentinel:
# 取消控制台懒加载
eager: true
transport:
# 控制台地址
dashboard: 127.0.0.1:8718
# nacos配置持久化
datasource:
ds1:
nacos:
server-addr: 127.0.0.1:8848
dataId: sentinel-ruoyi-gateway
groupId: DEFAULT_GROUP
data-type: json
rule-type: flow
4、启动sentinel
应用,可以看到我们在nacos
中配置的限流规则
RestTemplate 支持
Spring Cloud Alibaba Sentinel
支持对RestTemplate
调用的服务进行服务保护。需要在构造RestTemplate Bean
时添加@SentinelRestTemplate
注解。
RestTemplate
添加@SentinelRestTemplate
注解保护支持。
@Bean
@SentinelRestTemplate(blockHandler = "handleException", blockHandlerClass = ExceptionUtil.class, fallback = "fallback", fallbackClass = ExceptionUtil.class)
public RestTemplate restTemplate() {
return new RestTemplate();
}
服务熔断处理类ExceptionUtil.java
,必须使用静态方法。
import com.alibaba.cloud.sentinel.rest.SentinelClientHttpResponse;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpResponse;
public class ExceptionUtil
{
// 服务流量控制处理
public static ClientHttpResponse handleException(HttpRequest request, byte[] body,
ClientHttpRequestExecution execution, BlockException exception)
{
exception.printStackTrace();
return new SentinelClientHttpResponse("{\"code\":\"500\",\"msg\": \"服务流量控制处理\"}");
}
// 服务熔断降级处理
public static ClientHttpResponse fallback(HttpRequest request, byte[] body, ClientHttpRequestExecution execution,
BlockException exception)
{
exception.printStackTrace();
return new SentinelClientHttpResponse("{\"code\":\"500\",\"msg\": \"服务熔断降级处理\"}");
}
}
※OpenFeign 支持(常用)
其实不管是Hystrix
还是Sentinel
对于Feign
的支持,核心代码基本上是一致的,只需要修改依赖和配置文件即可。
1、添加依赖
<!-- SpringCloud Alibaba Nacos -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- spring cloud openfeign 依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
2、feign
开启sentinel
支持
spring:
cloud:
nacos:
discovery:
# 服务注册地址
server-addr: 127.0.0.1:8848
feign:
sentinel:
enabled: true
3、测试用户服务类RemoteUserService.java
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
/**
* 用户服务
*
* @author ruoyi
*/
@FeignClient(contextId = "remoteUserService", value = "ruoyi-system", fallbackFactory = RemoteUserFallbackFactory.class)
public interface RemoteUserService
{
/**
* 通过用户名查询用户信息
*
* @param username 用户名
* @return 结果
*/
@GetMapping(value = "/user/info/{username}")
public Object getUserInfo(@PathVariable("username") String username);
}
4、降级用户服务类处理RemoteUserFallbackFactory.java
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import feign.hystrix.FallbackFactory;
/**
* 用户服务降级处理
*
* @author ruoyi
*/
@Component
public class RemoteUserFallbackFactory implements FallbackFactory<RemoteUserService>
{
private static final Logger log = LoggerFactory.getLogger(RemoteUserFallbackFactory.class);
@Override
public RemoteUserService create(Throwable throwable)
{
log.error("用户服务调用失败:{}", throwable.getMessage());
return new RemoteUserService()
{
@Override
public Object getUserInfo(String username)
{
return "{\"code\":\"500\",\"msg\": \"用户服务熔断降级处理\"}";
}
};
}
}
5、启动类扫描配置
@EnableFeignClients(basePackages = "com.ruoyi")
eotype.Component;
import feign.hystrix.FallbackFactory;
/**
-
用户服务降级处理
-
@author ruoyi
*/
@Component
public class RemoteUserFallbackFactory implements FallbackFactory
{
private static final Logger log = LoggerFactory.getLogger(RemoteUserFallbackFactory.class);@Override
public RemoteUserService create(Throwable throwable)
{
log.error(“用户服务调用失败:{}”, throwable.getMessage());
return new RemoteUserService()
{
@Override
public Object getUserInfo(String username)
{
return “{“code”:“500”,“msg”: “用户服务熔断降级处理”}”;
}
};
}
}
5、启动类扫描配置
```java
@EnableFeignClients(basePackages = "com.ruoyi")