背景介绍
OpenFeign用来调用服务是很方便的, Sentinel是用来做限流的,都是微服务的必备功能,但又都具备调用失败后降级的功能,那么我们整合了Sentinel和OpenFeign后, 如果都配备了降级功能, 框架该如何选择降级功能,是优先使用还是只选择了某个降级其他配置就失效了呢?&
那么我们就来通过一个项目整合验证一下
项目依赖
组件 | 版本 |
org.springframework.boot<br>spring-boot-starter-parent | 2.3.12.RELEASE |
java.version | 1.8 |
org.springframework.cloud<br>spring-cloud-starter-openfeign | 2.2.7.RELEASE |
org.springframework.cloud<br>spring-cloud-alibaba-version | 2.2.7.RELEASE |
spring-cloud-starter-alibaba-nacos-discovery | |
spring-cloud-starter-alibaba-sentinel | |
spring-boot-starter-web |
项目结构
模块名 | 功能介绍 |
---|---|
commons | 通用模块,定义工具类,以及openfeign的调用接口定义,consumer和provider模块都会引用该模块 |
consumer | 消费模块,用于消费provider提供的接口 |
provider | 提供消费接口,实现来自于commons模块定义的openfeign接口 |
代码说明
在消费模块中,调用provider模块在commons模块定义的开发接口,代码如下:
// provider 模块
@RestController
public class TestController implements ProviderOpenApis {
@Value("${server.port}")
private String serverPort;
@GetMapping("/getServerPort")
public String getServerPort() {
return "Hello Nacos Discovery Port:" + serverPort;
}
//模仿数据库存储数据
public static HashMap<Integer, String> hashMap = new HashMap<>();
static {
hashMap.put(1, "鼠标");
hashMap.put(2, "键盘");
hashMap.put(3, "耳机");
}
@Override
public JsonResult<String> info(Integer id) {
String data = hashMap.get(id);
if (null == data) {
throw new NullPointerException(String.format("商品#%d不存在", id));
}
return new JsonResult<>(200, "ServerPort:" + serverPort + ", 商品:" + data);
}
}
//commons 模块
@Component
//表示远程调用服务名称
@FeignClient(value = "nacos-provider",fallback = ProviderOpenApisFallback.class)
public interface ProviderOpenApis {
@GetMapping("info/{id}")
JsonResult<String> info(@PathVariable("id") Integer id);
}
@Component
public class ProviderOpenApisFallback implements ProviderOpenApis{
@Override
public JsonResult<String> info(Integer id) {
return new JsonResult<>(500,"服务降级");
}
}
// consumer 模块
@RestController
public class DemoController {
@Autowired
private ProviderOpenApis providerOpenApis;
@GetMapping("/consumer/fallback/{id}")
//添加SentinelResource注解的fallback属性,同时设置方法来解决Java异常
@SentinelResource(value = "fallback", fallback = "fallbackError")
public JsonResult<String> fallback(@PathVariable Integer id) {
//通过Ribbon发起远程访问
return providerOpenApis.info(id);
}
public JsonResult<String> fallbackError(@PathVariable Integer id, Throwable e) {
return new JsonResult<>(500, "访问错误");
}
}
通过代码可以看出
我们在消费模块通过SentinelResource定义了资源, 并且通过fallback定义了调用失败或业务失败的调用方法
同时,我们在commons模块中定义了OpenFeign的访问接口ProviderOpenApis 用来访问provider模块提供的服务,并且通过fallback定义了访问失败是的调用类,ProviderOpenApisFallback 。 下面我们就可以测试结果了。
通过测试,我们看出调用了OpenFeign的接口 ProviderOpenApis中定义的ProviderOpenApisFallback ,所以如果同时存在定义fallback是会调用OpenFeign的。