强强联合:OpenFeign 整合 Sentinel

前言

书接前文:

微服务间的远程接口调用: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:

xml 复制代码
<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 :

yaml 复制代码
spring:
  application:
    name: open-feign-service

  cloud:
    nacos:
      discovery:
        server-addr: ${NACOS_SERVER:127.0.0.1:8848}
    sentinel:
      transport:
        dashboard: ${SENTINEL_DASHBOARD:localhost:8080}
        port: 8723
      web-context-unify: false
      datasource:
        flow:
          nacos:
            server-addr: ${NACOS_SERVER:127.0.0.1:8848}
            groupId: DEFAULT_GROUP
            dataId: sentinelFlowRule.json
            rule-type: flow

feign:
  client:
    config:
      default:
        connectTimeout: 5000
        readTimeout: 5000
      nacos-provider:
        connectTimeout: 1000
        readTimeout: 1000
        loggerLevel: full
  sentinel:
    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):

java 复制代码
/**
 * 业务异常。
 *
 * @author 苏渡苇
 */
public class BusinessException extends RuntimeException {

    private final String code;
    private final String message;

    public BusinessException(String code, String message) {
        super(message);
        this.code = code;
        this.message = message;
    }

    public String getCode() {
        return code;
    }

    @Override
    public String getMessage() {
        return message;
    }
}

然后使用 @RestControllerAdvice 进行全局异常处理:

java 复制代码
@ExceptionHandler(BusinessException.class)
public ResponseResult<String> businessException(BusinessException e) {
    LOGGER.info("code={}, message={}", e.getCode(), e.getMessage());
    return ResponseResult.fail(e.getCode(), e.getMessage());
}

这样,只要指定了抛出的异常类型,就会返回统一的响应格式。

操练

@FeignClient 的 fallback

在上一篇文章中,我们通过 FeignClient 接口调用远程的服务:

java 复制代码
@FeignClient(name = "nacos-provider", fallback = ProductServiceImpl.class)
public interface ProductService {

    @GetMapping("/product/{id}")
    String getProductById(@PathVariable("id") Long id);
}

定义 fallback 实现类:

java 复制代码
@Component
public class ProductServiceImpl implements ProductService {

    @Override
    public String getProductById(Long id) {
        log.error("调用接口 getProduct 失败,id={}", id);
        throw new BusinessException(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 使用,本例中有如下定义:

java 复制代码
@GetMapping("/product/{id}")
@SentinelResource(value = "getProduct",
                  blockHandler = "getProductBlock",
                  fallback = "getProductFallback")
public String getProduct(@PathVariable("id") Long id) {
    return productService.getProductById(id);
}

public String getProductBlock(Long id, BlockException e) {
    log.error("访问资源 getProduct 被限流,id={}", id);
    throw new BusinessException("C0002", "访问资源 getProduct 被限流");
}

public String getProductFallback(Long id) {
    log.error("访问资源 getProduct fallback");
    return "请稍后重试";
}

在前面的准备工作中,我们已经配置了 Sentinel 资源限流规则持久化到 Nacos,现在 Nacos 中配置一下资源 getProduct 的限流规则:

json 复制代码
[
  {
    "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

相关推荐
洋就在江州10 小时前
gitlab-cicd 离线集成——springboot-cicd (非docker形式,shell形式)
java·spring boot·后端·ci/cd·gitlab·gitlab-runner
令狐少侠201110 小时前
centos7 下,使用docker 部署IOT 调试平台,ThingsBoard 并完美启动
java·spring boot·iot
Joy T11 小时前
从 Nginx 到 Gateway 再到微服务:一次 AI 请求的完整链路
nginx·微服务·gateway·controller·路由转发·ai service·接口错误排查
省钱兄--zs12 小时前
24小时自助健身房系统软件开发实战:从架构设计到部署全指南
java·数据仓库·spring boot·系统架构·需求分析
IT研究室12 小时前
最新计算机毕业设计选题推荐-基于spring boot的智慧教学资源管理与互动交流平台-网站-文档指导-Java-springboot
java·spring boot·课程设计
程序猿_极客12 小时前
【免费】分享一套优质的基于Java的智慧养老院管理系统的设计与实现(带可视化),源码+文档+视频详解(讲解)
java·spring boot·后端·养老院管理系统
Thomas.Sir13 小时前
第19课:Gateway过滤器、全局拦截、请求响应统一处理
spring cloud·gateway
程序猿_极客13 小时前
【免费】分享一套优质的基于SpringBoot的旅游管理系统的设计与实现(带智能推荐算法功能),源码+文档+视频详解(讲解)
java·spring boot·课程设计·旅游管理系统·计算机专业项目
专业程序开发源13 小时前
django便利店外卖后台管理系统19650-计算机课程设计、毕业设计
java·vue.js·spring boot·后端·python·django·课程设计
马剑威(威哥爱编程)13 小时前
【AI全栈后端12-09】Spring Boot 用流式输出做打字机对话:点下去不再干等
java·人工智能·spring boot·后端