OpenFeign整合Sentinel,由浅入深,搭建属于自己的脚手架

开发 架构
Sentinel是阿里巴巴开源的一款微服务流量控制组件。是面向分布式、多语言异构化服务架构的流量治理组件,主要以流量为切入点,从流量路由、流量控制、流量整形、熔断降级、系统自适应过载保护、热点流量防护等多个维度来帮助开发者保障微服务的稳定性。

本文由浅人深,带你了解如何在项目中整合OpenFeign与Sentinel,分析Sentinel源码,并打造自己的Sentinel脚手架。

Sentinel是什么

Sentinel是阿里巴巴开源的一款微服务流量控制组件。是面向分布式、多语言异构化服务架构的流量治理组件,主要以流量为切入点,从流量路由、流量控制、流量整形、熔断降级、系统自适应过载保护、热点流量防护等多个维度来帮助开发者保障微服务的稳定性。

OpenFeign调用

我们先看一下,没有整合Sentinel,OpenFeign调用异常时,是怎样的情况。假定存在两个服务,order和user,然后再order服务中,通过feign调用user中的接口。

公共组件中定义接口:

@FeignClient(name = "xdty-user")
public interface UserApi {

    @GetMapping("/getUserInfo")
    ResponseResult getUserInfo();
}

user服务中实现接口:

public class UserController implements UserApi {
    @Override
    public ResponseResult getUserInfo() {
        int i = 1/0; //模拟异常
        return new ResponseResult("200","user info");
    }
}

order服务中调用user服务中的接口:

@RestController
public class OrderController implements OrderApi {

    @Autowired
    private UserApi userApi;

    @Override
    public ResponseResult getOrderInfo() {
        return userApi.getUserInfo();
    }
}

利用postman访问order服务。

返回接口:

可以看到,这样的返回值,是非常不友好的,对于项目而言,不管接口成功与否,都应有统一的返回,如:code,message。

OpenFeign整合Sentinel

引入依赖:

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>

启用OpenFeign整合Sentinel的自动配置。熔断是在consumer端实现的,所以在consumer端的application.yaml配置文件中添加如下配置。

feign:
  sentinel:
    enabled: true

定义一个容错的处理类,当调用远程接口失败或超时时,会调用对应接口的容错逻辑。

public class UserApiFallback implements UserApi {

    @Override
    public ResponseResult getUserInfo() {
        return new ResponseResult("503","用户服务异常");
    }
}

@Component
public class UserApiFallbackFactory implements FallbackFactory<UserApi> {
    @Override
    public UserApi create(Throwable cause) {
        return new UserApiFallback();
    }
}

@FeignClient 注解上增加 fallbackFactory属性。

@FeignClient(name = "xdty-user",fallbackFactory = UserApiFallbackFactory.class)
public interface UserApi {

    @GetMapping("/getUserInfo")
    ResponseResult getUserInfo();
}

再次调用接口。

可以发现,服务异常后,会进行降级处理,返回统一定义的异常。

全局异常封装分析

上述代码,增加了异常处理逻辑,但存在一个问题,就是每次都要为其设置fallbackFactory参数。导致项目中会多出很多冗余代码。那我们能不能有一个自己定制化的默认Fallback去处理这些相同的事情呢?

要想解决这个问题,需要先了解sentinel中fallback的机制。前面提到,要使用sentinel需要配置文件中指定feign.sentinel.enabled=true。看到SentinelFeignAutoConfiguration的代码实现,我想大家也就明天这样配置的原因了。

@ConditionalOnProperty 中 feign.sentinel.enabled 起了决定性作用,这也就是为什么我们需要在配置文件中指定 feign.sentinel.enabled=true。

接下来看 SentinelFeign.builder 里面的实现:

build方法中重新实现了super.invocationHandlerFactory方法,也就是动态代理工厂,构建的是InvocationHandler对象。

build中会获取Feign Client中的信息,比如fallback,fallbackFactory等,然后创建一个SentinelInvocationHandler,SentinelInvocationHandler继承了InvocationHandler。

SentinelInvocationHandler中的invoke方法里面进行熔断限流的处理。

从这段代码我就可以看出,在没有配置fallback时,并没有向SentinelInvocationHandler构造方法中传入FallbackFactory。这样的话我们就有了思路:

  • 编写公共FallbackFactory
  • 改写SentinelFeign使得fallbackFactory为void.class时,我们传入自己的公共FallbackFactory实例。

打造自己的sentinel脚手架

接下来,我们沿着sentinel的思路,编写一个属于自己的小小脚手架,实现统一的兜底方法。

定义全局的fallback处理器。

定义一个全局的FallbackFactory。

重新实现spring-cloud-starter-alibaba-sentinel下的SentinelFeign。

注入我们的SentinelFeign Bean。

注:这里使用AutoConfigureBefore注解,要想该注解生效,必须把自定义的配置类变成自动配置类。

这样,以后只要定义基本属性@FeignClient,不需要再配置fallBackFactory,就可以完成统一的兜底方法了。

责任编辑:姜华 来源: 今日头条
相关推荐

2020-08-19 08:55:47

Redis缓存数据库

2021-05-21 05:22:52

脚手架工具项目

2021-01-07 05:34:07

脚手架JDK缓存

2022-07-18 07:58:46

Spring工具工具类

2021-12-19 07:22:16

Create前端工具

2016-08-10 14:59:41

前端Javascript工具

2016-09-07 15:35:06

VueReact脚手架

2021-12-23 10:35:32

SpringCloud脚手架架构

2021-04-28 16:10:48

开发脚手架 Spring

2020-03-20 08:32:41

物联网脚手架传感器

2021-08-30 06:59:06

StrviewAppStrview.js项目

2021-05-13 17:02:38

MDC脚手架日志

2021-07-13 18:42:38

Spring Boot脚手架开发

2021-04-13 14:47:53

认证授权Java

2019-12-25 15:20:48

前端脚手架命令

2018-06-11 14:39:57

前端脚手架工具node.js

2018-08-30 16:08:37

Node.js脚手架工具

2022-04-24 11:33:47

代码管理工程

2021-06-02 17:58:49

脚手架 幂等性前端

2021-02-19 22:43:50

开发脚手架Controller
点赞
收藏

51CTO技术栈公众号