程序员,你知道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也有对应的适配器;有空老顾再写一篇文章。谢谢!!!