简介
上一篇博客中,针对 @SentinelResources 注解,做了个简单的测试Demo,这一篇文章重点说明总结 @SentinelResources 的详细使用和配置。
《Sentinel实现熔断、限流、降级》
与HystrixCommand相比
@HystrixCommand 和 @SentinelResources 注解的功效总体而言是类似的。
springcloud 第一代不在迭代更新,阿里团队在springcloud第一代的基础上,做了一层封装,原则上还是使用大局化配置。
简单案例
之前的配置主要根据 URL
的形式进行流控
、限流
的配置和使用,本次依据 @SentinelResources 注解实现资源名称
方式进行配置操作。
新建一个处理类。
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.fastjson.JSONObject;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ResourcesController {
@RequestMapping("/resources1")
@SentinelResource(value = "resources1",blockHandler = "handler")
public JSONObject resources1(){
JSONObject json = new JSONObject();
json.put("code",200);
json.put("msg","请求成功!");
return json;
}
public JSONObject handler(BlockException e){
JSONObject json = new JSONObject();
json.put("code",300);
json.put("msg","请求降级!");
return json;
}
}
启动项目,当不配置 流控规则
时,快速请求访问:
配置流控规则
:
请求测试:
异常回执配置
在Hystrix 中,出现异常后,会进入降级处理流程,但在 Sentinel 中出现异常,并不会进入降级处理操作。
异常测试
增加新的测试代码逻辑:
// ================= 异常操作
@RequestMapping("/resources2")
@SentinelResource(value = "resources2",blockHandler = "handler2")
public JSONObject resources2(){
int a = 10/0;
JSONObject json = new JSONObject();
json.put("code",200);
json.put("msg","请求成功!");
return json;
}
public JSONObject handler2(BlockException e){
JSONObject json = new JSONObject();
json.put("code",300);
json.put("msg","请求降级!");
return json;
}
异常降级处理操作流程
采取@SentinelResources 注解中的
fallback
属性配置异常降级流程。
// ================= 异常操作
@RequestMapping("/resources2")
@SentinelResource(value = "resources2",
blockHandler = "handler2",
fallback = "fallback2")
public JSONObject resources2(){
int a = 10/0;
JSONObject json = new JSONObject();
json.put("code",200);
json.put("msg","请求成功!");
return json;
}
public JSONObject fallback2(){
JSONObject json = new JSONObject();
json.put("code",300);
json.put("msg","fallback2 请求降级!");
return json;
}
public JSONObject handler2(BlockException e){
JSONObject json = new JSONObject();
json.put("code",300);
json.put("msg","请求降级!");
return json;
}
深层次的思考
@SentinelResources 注解中,每次进行配置流控降级处理操作时,都需要指定一个或多个
blockHandler
;或者出现异常降级时,一个处理方法指定一个fallback
。
能否有一种全局化的配置,只需要进行调用即可呢?
答案是有的,可以采取专门定义一个 blockHandler
类和fallback
类的方式。
定义两个类,分别为 blockHandler
类和fallback
类。
其中,blockHandler
类的处理方法有
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.fastjson.JSONObject;
public class HandlerGlobal {
public static JSONObject handler1(String msg,BlockException e){
JSONObject json = new JSONObject();
json.put("code",300);
json.put("msg","请求降级!----1");
return json;
}
public static JSONObject handler2(String msg,BlockException e){
JSONObject json = new JSONObject();
json.put("code",300);
json.put("msg","请求降级!----2");
return json;
}
}
fallback
类的处理方法有:
import com.alibaba.fastjson.JSONObject;
public class Fallback {
public static JSONObject fallback1(String msg){
JSONObject json = new JSONObject();
json.put("code",300);
json.put("msg","fallback1 请求降级!");
return json;
}
public static JSONObject fallback2(String msg){
JSONObject json = new JSONObject();
json.put("code",300);
json.put("msg","fallback2 请求降级!");
return json;
}
}
处理类上的引用案例:
//============全局化调用
@RequestMapping("/resources3")
@SentinelResource(value = "resources3",
blockHandlerClass = HandlerGlobal.class ,
blockHandler = "handler2",
fallbackClass = Fallback.class,
fallback = "fallback1")
public JSONObject resources3(String msg){
if("1".equalsIgnoreCase(msg)){
int a = 10/0;
}
JSONObject json = new JSONObject();
json.put("code",200);
json.put("msg","请求成功!");
return json;
}
重启项目,并配置流控规则
请求测试:
增加异常逻辑,请求测试:
[注意:] 几个需要注意的地方
1、Sentinel 的
blockHandler
处理方法中,必须携带参数BlockException e
,否则无法指向。
2、全局化的blockHandler
处理方法,必须为static
。
3、全局化的fallback
处理方法,必须为static
。
4、blockHandler
和fallback
两个方法中的携带参数
必须和请求类
的保持一致!
@SentinelResources中的其他参数
- value
资源名称,必需项(不能为空) - entryType
entry 类型,可选项(默认为EntryType.OUT
) - blockHandler / blockHandlerClass
blockHandler 对应处理 BlockException 的函数名称,可选项。
blockHandler 函数访问范围需要是public
,返回类型需要与原方法相匹配
,参数类型需要和原方法相匹配
并且最后加一个额外的参数,类型为 BlockException
。
blockHandler 函数默认需要和原方法在同一个类中。
若希望使用其他类的函数,则可以指定 blockHandlerClass 为对应的类的 Class 对象,注意对应的函数必需为static
函数,否则无法解析。 - fallback / fallbackClass
fallback 函数名称,可选项,用于在抛出异常的时候提供 fallback 处理逻辑。
fallback 函数可以针对所有类型的异常(除了 exceptionsToIgnore 里面排除掉的异常类型)进行处理。
- fallback 函数签名和位置要求:
返回值类型
必须与原函数返回值类型一致;方法参数
列表需要和原函数一致,或者可以额外多一个 Throwable 类型
的参数用于接收对应的异常。- fallback 函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定 fallbackClass 为对应的类的 Class 对象,注意对应的函数必需为
static
函数,否则无法解析。
- defaultFallback
默认的 fallback 函数名称,可选项,通常用于通用的 fallback 逻辑(即可以用于很多服务或方法)。
默认 fallback 函数可以针对所有类型的异常(除了 exceptionsToIgnore 里面排除掉的异常类型)进行处理。
若同时配置了 fallback 和 defaultFallback,则只有 fallback 会生效
。
- defaultFallback 函数签名要求:
返回值类型
必须与原函数返回值类型一致;方法参数
列表需要为空,或者可以额外多一个 Throwable 类型的参数用于接收对应的异常。- defaultFallback 函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定 fallbackClass 为对应的类的 Class 对象,注意对应的函数必需为
static
函数,否则无法解析。
- exceptionsToIgnore
用于指定哪些异常被排除掉,不会计入异常统计中,也不会进入 fallback 逻辑中,而是会原样抛出。