前言
书接前文:
微服务间的远程接口调用:OpenFeign 的使用
当项目中使用了OpenFeign后,可以很方便的进行远程服务调用,现在有个问题,假如远程服务出现故障了,调不了远程的接口,这边又着急等着返回结果,怎么办呢?
当然是使用服务降级,本篇就使用OpenFeign进行远程调用,并结合Sentinel对出现的异常、故障等问题进行服务降级。
准备
本章代码仓库:https://github.com/iweidujiang/spring-cloud-alibaba-lab
示例模块:
08-feign-sentinel,在feign-sentinel-service中整合 OpenFeign 与 Sentinel。
仍以前面第 7 章open-feign-service的思路为调用方、nacos-provider为提供方来进行操练(本章代码位于08-feign-sentinel目录)。
Jar 包依赖
feign-sentinel-service除引入spring-cloud-starter-openfeign外,再引入spring-cloud-starter-alibaba-sentinel组件;使用 Nacos 配置中心做 Sentinel 限流规则持久化,还需引入spring-cloud-alibaba-sentinel-datasource和sentinel-datasource-nacos:
<dependency><groupId>io.github.iweidujiang</groupId><artifactId>feign-sentinel-common</artifactId><version>1.0.0</version></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId></dependency><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-sentinel</artifactId></dependency><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-alibaba-sentinel-datasource</artifactId></dependency><dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-datasource-nacos</artifactId></dependency>配置文件
配置文件application.yml:
spring:application:name:open-feign-servicecloud:nacos:discovery:server-addr:${NACOS_SERVER:127.0.0.1:8848}sentinel:transport:dashboard:${SENTINEL_DASHBOARD:localhost:8080}port:8723web-context-unify:falsedatasource:flow:nacos:server-addr:${NACOS_SERVER:127.0.0.1:8848}groupId:DEFAULT_GROUPdataId:sentinelFlowRule.jsonrule-type:flowfeign:client:config:default:connectTimeout:5000readTimeout:5000nacos-provider:connectTimeout:1000readTimeout:1000loggerLevel:fullsentinel:enabled:true限流规则 JSON 示例见仓库08-feign-sentinel/config/sentinelFlowRule.json。
这里增加了Sentinel的数据持久化内容,以及激活OpenFeign与Sentinel联合使用的feign.sentinel.enabled=true配置。
全局统一异常处理
不管是Sentinel限流后返回,还是OpenFeign的fallback返回,本质上他们都是出现异常了,这里配置一下全局的统一异常处理。
首先,增加一个业务异常类(io.github.iweidujiang.lab08.common.exception.BusinessException):
/** * 业务异常。 * * @author 苏渡苇 */publicclassBusinessExceptionextendsRuntimeException{privatefinalStringcode;privatefinalStringmessage;publicBusinessException(Stringcode,Stringmessage){super(message);this.code=code;this.message=message;}publicStringgetCode(){returncode;}@OverridepublicStringgetMessage(){returnmessage;}}然后使用@RestControllerAdvice进行全局异常处理:
@ExceptionHandler(BusinessException.class)publicResponseResult<String>businessException(BusinessExceptione){LOGGER.info("code={}, message={}",e.getCode(),e.getMessage());returnResponseResult.fail(e.getCode(),e.getMessage());}这样,只要指定了抛出的异常类型,就会返回统一的响应格式。
操练
@FeignClient 的 fallback
在上一篇文章中,我们通过FeignClient接口调用远程的服务:
@FeignClient(name="nacos-provider",fallback=ProductServiceImpl.class)publicinterfaceProductService{@GetMapping("/product/{id}")StringgetProductById(@PathVariable("id")Longid);}定义 fallback 实现类:
@ComponentpublicclassProductServiceImplimplementsProductService{@OverridepublicStringgetProductById(Longid){log.error("调用接口 getProduct 失败,id={}",id);thrownewBusinessException(ResponseCode.RPC_ERROR.getCode(),ResponseCode.RPC_ERROR.getMessage());}}Tips:ResponseCode.RPC_ERROR在feign-sentinel-common模块中定义(C0001/ 远程调用失败)。
OK,不启动服务提供方nacos-provider,直接调用接口测试。
接口返回:
控制台打印信息:
这样就实现了fallback的容错处理,即时远程服务不可用,也能进行降级处理。
@SentinelResource 限流
在 Controller 层使用 FeignClient 定义的接口进行远程调用服务时,还可以定义 Sentinel 资源,并设置规则对资源进行限流。
@SentinelResource的一些使用方法在前几篇文章中已有提及,这里再结合OpenFeign使用,本例中有如下定义:
@GetMapping("/product/{id}")@SentinelResource(value="getProduct",blockHandler="getProductBlock",fallback="getProductFallback")publicStringgetProduct(@PathVariable("id")Longid){returnproductService.getProductById(id);}publicStringgetProductBlock(Longid,BlockExceptione){log.error("访问资源 getProduct 被限流,id={}",id);thrownewBusinessException("C0002","访问资源 getProduct 被限流");}publicStringgetProductFallback(Longid){log.error("访问资源 getProduct fallback");return"请稍后重试";}在前面的准备工作中,我们已经配置了 Sentinel 资源限流规则持久化到 Nacos,现在 Nacos 中配置一下资源getProduct的限流规则:
[{"resource":"getProduct","limitApp":"default","grade":1,"count":1,"strategy":0,"controlBehavior":0,"clusterMode":false}]限流规则是 QPS 阈值为1,只要我1秒大于1次请求就会被限流。
启动远程服务nacos-provider,下面来验证一下。
1秒只发一个请求的结果:
1秒内快速刷新几次,造成QPS大于1,将会被限流:
小结
OpenFeign整合Sentinel需要引入Sentinel相关依赖包;- 在配置文件通过
feign.sentinel.enabled=true来开启 Feign 与 Sentinel的结合使用; - 在@FeignClient注解中增加
fallback属性,该属性定义远程接口访问有问题时的容错处理逻辑的类; fallback定义的类需实现@FeignClient定义的接口。
点个赞再走吧~
先赞后看,养成习惯。
举手之劳,赞有余香。
本文创作于 2022-08-19 。
代码仓库已更新:https://github.com/iweidujiang/spring-cloud-alibaba-lab