程序员,你知道Sentinel限流、降级的统一处理吗?

前言

之前老顾先容了sentinel的fallback、blockhandler;不知道小伙伴们有没有注意到一个问题?老顾带着大家来看看。

问题一

sentinel的默认流控返回的是:


1.  `BlockedbySentinel(flow limiting)`

当然大家可以通过@SentinelResource设置定制的fallback、blockhandler方法

但是大家也不可能每个限制的方法上面,都要去设置@SentinelResource;这样代码太冗余了。

解决方案

自定义限流页面

默认情况下,当请求被限流时会返回默认的提示页面。可通过二种方式设置自定义的跳转 URL。

方式一:


1.  `WebServletConfig.setBlockPage(blockPage)方法`

方式二:


1.  `JVM -Dcsp.sentinel.web.servlet.block.page=xxx`

在启动应用的时候,加入启动参数:

1.  `//设置全局生效,被流控的所有页面都会跳转到这里。`

2.  `-Dcsp.sentinel.web.servlet.block.page=https://www.x.com`

上面的两种方式,都能够做到一旦出现流控异常,就会跳转到指定页面。

更灵活的处理方式

上面的解决方案,只是跳转到另一个页面,但如果大家只要得到json返回值呢;那就需要此方式了,定义UrlBlockHandler接口限流处理逻辑,并将其注册至 WebCallbackManager

首先自定义一个UrlBlockHandler实现类

在一个初始化方法里面注册此UrlBlockHandler

来看看效果

注意此解决方案:需要引入一个jar包,这个是基于servlet


1.  `<dependency>`

2.  `<groupId>com.alibaba.csp</groupId>`

3.  `<artifactId>sentinel-web-servlet</artifactId>`

4.  `</dependency>`

问题二

在spring cloud中大家会经常使用到feign,在@FeignClient中大家可以指定fallback,大家来看看案例:

以上就是常规的在使用@FeignClient注解时,加上fallbackFactory;但每次都要为其设置fallbackFactory参数。导致项目中会多出很多冗余代码。那大家能不能有一个自己定制化的默认Fallback去处理这些相同的事情呢?

解决方案

在使用sentinel时,需要引入一个jar包:

1.  `<dependency>`

2.  `<groupId>com.alibaba.cloud</groupId>`

3.  `<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>`

4.  `</dependency>`

在这个jar包中,有一段源码:

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

  • 编写公共FallbackFactory

  • 改写SentinelFeign使得fallbackFactory为void.class时,大家传入自己的公共FallbackFactory实例

让大家一起上代码吧!

先定义全局的fallback处理器

再定义一个全局的FallbackFactory

再后面大家需要重新实现spring-cloud-starter-alibaba-sentinel下的SentinelFeign

上面的代码其实是仿照SentinelFeign源码的,唯一的区别就是画上红色的框的。

注意:其中有个方法setAccessible,这个是因为SentinelInvocationHandler的构造方法是私有方法。

其实还有一种方案,就是把重写 的SentinelFeign类,放到com.alibaba.cloud.sentinel.feign包下,也就是在自己的项目中,新建com.alibaba.cloud.sentinel.feign包

最后注入大家的SentinelFeign Bean

注意:一定要在配置文件中配置feign.sentinel.enabled=true

到这里就可以了,以后只要定义基本属性@FeignClient,不需要再配置fallBackFactory了哦。

当然你还有特殊的需求,再自定义的可以了。

总结

通过此文章,小伙伴就可以更好的使用Sentinel了,更方便的编写统一的兜底方法了。如果有人使用dubbo时,sentinel也有对应的适配器;有空老顾再写一篇文章。谢谢!!!