由于hystrix的停止更新,以及阿里Sentinel在历年双十一的贡献。项目中使用了Sentinel,今天我们来讲讲Sentinel的入门教程,本文使用1.6.3版本进行讲解
本文通过Sentinel_dashBoard进行讲解,当然不引入监控看板也能实现限流熔断降级功能,但是监控看板能够直观的看到请求的QPS,成功率等等,同时可以实时的进行降级限流策略的修改与新建。
sentinel_dashboard的引入
https://github.com/alibaba/Sentinel/releases,下载sentinel-dashboard-1.6.3.jar
由于dashboard是springboot的项目,在CMD模式下使用命令
java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.6.3.jar
进行控制看板服务的启动。
其中,-Dserver.port=8080 代表看板项目的端口号,
-Dcsp.sentinel.dashboard.server=localhost:8080 代表本看板服务将会注册到自己的看板上,
-Dproject.name=sentinel-dashboard 代表本看板服务的项目名称。
访问localhost:8080;输入用户名,密码,均是sentinel,如果要自定义用户名和密码,在启动命令加上-Dsentinel.dashboard.auth.username=sentinel,-Dsentinel.dashboard.auth.password=123456即可。
我们可以看到控制台自身的服务已经注册到了控制台上。
接下来,引入需要接入sentinel功能的项目。
maven依赖
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-annotation-aspectj</artifactId>
<version>1.6.3</version>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-core</artifactId>
<version>1.6.3</version>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-transport-simple-http</artifactId>
<version>1.6.3</version>
</dependency>
编写启动类
package sentile;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SentileApp {
public static void main(String[] args) {
SpringApplication.run(SentileApp.class, args);
}
}
@SentinelResource
使用这个注解,可以对我们要进行限流的资源接口当出现异常时进行捕获,比如下面的这个接口 getByResource,@SentinelResource的使用很简单,最基本的就是配置资源名称,加上blockHandler ,blockHandler 里面是触发限流规则时的方法,即在这个方法中进行后续的业务处理,如抛出友好的提示等
@RestController
public class RateLimitController {
@GetMapping("/getByResource")
@SentinelResource(value = "getByResource",blockHandler = "handleException")
public ResponseResult getByResource(){
return ResponseResult.success("this is success result");
}
public ResponseResult handleException(BlockException blockExe){
return ResponseResult.fail(412,"is block:" + blockExe.getMessage());
}
}
blockHandler需要特别注意,必须和源方法的参数名还有返回值类型保持一致才会被解析成功。
同样,我们在dashboard中对这个接口进行配置,每秒1次的QPS,正常访问时,
快速访问时,就走到了降级后的方法中了
但是如果这么做的话,很明显的一个问题就是,异常处理的逻辑和业务耦合在一起,代码会越来越膨胀,后续不方便管理,因此我们单独提供一个类,这个类专门用于提供不同的异常方法,
public class CustomerBlockHandler {
public static ResponseResult handleException(BlockException exe){
return ResponseResult.fail(412,"is block:" + exe.getMessage());
}
}
那么在接口中我们就可以这样调用
@GetMapping("/getByResource1")
@SentinelResource(value = "customerBlockHandler",
blockHandlerClass = CustomerBlockHandler.class,
blockHandler = "handleException")
public ResponseResult getByResource1(){
return ResponseResult.success("this is success result");
}
同样,再在控制台配置限流规则后可以达到我们的效果,
关于降级
还以前面的 /testFlow接口为例:
服务降级可能大家并不陌生,即在一个应用中,当请求到某个服务接口长时间没有响应时,为了避免更多的请求进来造成服务的雪崩,我们采取一种机制,让程序快速返回结果,或者干脆抛出友好的提示,让调用者知道当前的服务不可用,这样就不至于出现服务端的线程资源被耗尽的情况
对于上述图中的配置,解释起来就是:超过了每秒请求的阈值之后,后面的请求再过来的时候,在5秒之内,服务处于不可用的状态,5秒之后,服务恢复,我们通过快速刷新接口,可以看到效果
开启条件:1秒内,有一个/testFlow请求过来,便开启熔断检查
触发熔断:当前时间窗口内,有超过50%的请求产生异常
触发熔断之后的5秒内,再有请求过来,都会被blocked
有这么一种情况,当调用接口时,由于参数校验不通过,或者后端抛出了运行时的异常,如果没有合适的处理,将会出现下面的结果,
@GetMapping("/createOrder")
@SentinelResource(value = "fallback")
public String createOrder(String id){
if(id.equals("2")){
throw new IllegalArgumentException("参数异常");
}
return orderService.createOrder(id);
}
显然,这是一种不太友好的情况,对于这种情况,就可以使用Sentinel的服务降级进行处理了,改造后的接口如下:
@GetMapping("/createOrder")
@SentinelResource(value = "fallback",fallback = "getFallBack")
public String createOrder(String id){
if(id.equals("2")){
throw new IllegalArgumentException("参数异常");
}
return orderService.createOrder(id);
}
public static String getFallBack(String id,Throwable t){
return id + ":=====>" + t.getMessage();
}
再次访问时,可以看到出现了我们的降级方法,也可以理解为兜底的方法
同样我们可以利用一个单独的类,统一处理这样的降级,如下:
@GetMapping("/createOrder")
@SentinelResource(value = "fallback",fallbackClass = MyFallBackHandler.class,fallback = "getFallBack")
public String createOrder(String id){
if(id.equals("2")){
throw new IllegalArgumentException("参数异常");
}
return orderService.createOrder(id);
}
public class MyFallBackHandler {
public static String getFallBack(String id,Throwable t){
return id + ":=====>" + t.getMessage();
}
}
其实在真实的开发中,不管是单应用还是微服务之间的调用,一般情况下可能出现的异常我们基本上都是可以提前预知的,如超时异常,系统参数异常等,这样我们就可以预设部分的降级处理方法,在适当的接口上面进行引用即可
本文由 admin 创作,采用 知识共享署名4.0
国际许可协议进行许可
本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名
最后编辑时间为:2022-08-09 22:42:32