按资源名称&url地址限流
接口代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
@GetMapping("/byResource")
@SentinelResource(value = "byResource", blockHandler = "handleException")
public CommonResult byResource() {
return CommonResult.success("按资源名称限流测试OK");
}
@GetMapping("/byUrl")
@SentinelResource(value = "byUrl", blockHandler = "handleException")
public CommonResult byUrl() {
return CommonResult.success("按url限流测试OK");
}
public CommonResult handleException(BlockException exception) {
return CommonResult.error(444, exception.getClass().getCanonicalName() + "\t 服务不可用");
}
|
按资源名称配置限流规则

按url地址限流

狂刷两个接口,结果如下:
http://localhost:8401/byUrl
1
|
Blocked by Sentinel (flow limiting)
|
http://localhost:8401/byResource
1
2
3
4
5
|
{
"code": 444,
"desc": "com.alibaba.csp.sentinel.slots.block.flow.FlowException\t 服务不可用",
"data": null
}
|
结论
按url地址限流,blockHandler不生效,只会进行默认处理,使用资源名进行限流,会使用自定义的blockHandler方法。
问题
- 自定义的处理方法和业务耦合在一起,不直观
- 每个业务方法都添加一个兜底的方法,那代码膨胀加剧
- 全局统一的处理方法没有体现
客户自定义限流处理逻辑
创建customerBlockHandler类用于自定义限流处理逻辑
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
package com.eh.cloudalibaba.sentinel;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.eh.cloud2020.common.entity.CommonResult;
/**
* 自定义限流处理类
*/
public class CustomBlockHandler {
public static CommonResult handlerException1(BlockException exception) {
return CommonResult.error(444, "按客戶自定义,global handlerException----1");
}
public static CommonResult handlerException2(BlockException exception) {
return CommonResult.error(444, "按客戶自定义,global handlerException----2");
}
}
|
修改@SentinelResource属性配置
1
2
3
4
5
6
7
8
9
10
11
|
@GetMapping("/byResource")
@SentinelResource(value = "byResource", blockHandlerClass = CustomBlockHandler.class, blockHandler = "handlerException1")
public CommonResult byResource() {
return CommonResult.success("按资源名称限流测试OK");
}
@GetMapping("/byUrl")
@SentinelResource(value = "byUrl", blockHandlerClass = CustomBlockHandler.class, blockHandler = "handlerException1")
public CommonResult byUrl() {
return CommonResult.success("按url限流测试OK");
}
|
再次狂刷两个接口,可以看到
按资源名称配置限流规则的接口访问会使用自定义处理
1
2
3
4
5
|
{
"code": 444,
"desc": "按客戶自定义,global handlerException----1",
"data": null
}
|
按url地址配置限流规则的接口访问则依然会使用系统默认处理
1
|
Blocked by Sentinel (flow limiting)
|
@SentinelResource 属性介绍
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
|
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface SentinelResource {
/**
* @return name of the Sentinel resource
*/
String value() default "";
/**
* @return the entry type (inbound or outbound), outbound by default
*/
EntryType entryType() default EntryType.OUT;
/**
* @return the classification (type) of the resource
* @since 1.7.0
*/
int resourceType() default 0;
/**
* @return name of the block exception function, empty by default
*/
String blockHandler() default "";
/**
* The {@code blockHandler} is located in the same class with the original method by default.
* However, if some methods share the same signature and intend to set the same block handler,
* then users can set the class where the block handler exists. Note that the block handler method
* must be static.
*
* @return the class where the block handler exists, should not provide more than one classes
*/
Class<?>[] blockHandlerClass() default {};
/**
* @return name of the fallback function, empty by default
*/
String fallback() default "";
/**
* The {@code defaultFallback} is used as the default universal fallback method.
* It should not accept any parameters, and the return type should be compatible
* with the original method.
*
* @return name of the default fallback method, empty by default
* @since 1.6.0
*/
String defaultFallback() default "";
/**
* The {@code fallback} is located in the same class with the original method by default.
* However, if some methods share the same signature and intend to set the same fallback,
* then users can set the class where the fallback function exists. Note that the shared fallback method
* must be static.
*
* @return the class where the fallback method is located (only single class)
* @since 1.6.0
*/
Class<?>[] fallbackClass() default {};
/**
* @return the list of exception classes to trace, {@link Throwable} by default
* @since 1.5.1
*/
Class<? extends Throwable>[] exceptionsToTrace() default {Throwable.class};
/**
* Indicates the exceptions to be ignored. Note that {@code exceptionsToTrace} should
* not appear with {@code exceptionsToIgnore} at the same time, or {@code exceptionsToIgnore}
* will be of higher precedence.
*
* @return the list of exception classes to ignore, empty by default
* @since 1.6.0
*/
Class<? extends Throwable>[] exceptionsToIgnore() default {};
}
|
说明
属性名 |
是否必填 |
说明 |
value |
是 |
资源名称 。(必填项,需要通过 value 值找到对应的规则进行配置) |
entryType |
否 |
entry类型,标记流量的方向,取值IN/OUT,默认是OUT |
blockHandler |
否 |
处理BlockException的函数名称(可以理解为对Sentinel的配置进行方法兜底)。函数要求: 1.必须是 public 修饰 2.返回类型与原方法一致 3. 参数类型需要和原方法相匹配,并在最后加 BlockException 类型的参数。 4. 默认需和原方法在同一个类中。若希望使用其他类的函数,可配置 blockHandlerClass ,并指定blockHandlerClass里面的方法。 |
blockHandlerClass |
否 |
存放blockHandler的类。 对应的处理函数必须 public static 修饰,否则无法解析,其他要求:同blockHandler。 |
fallback |
否 |
用于在抛出异常的时候提供fallback处理逻辑(可以理解为对Java异常情况方法兜底)。 fallback函数可以针对所有类型的异常(除了 exceptionsToIgnore 里面排除掉的异常类型)进行处理。函数要求: 1.返回类型与原方法一致 2.参数类型需要和原方法相匹配,Sentinel 1.6开始,也可在方法最后加 Throwable 类型的参数。 3.默认需和原方法在同一个类中。若希望使用其他类的函数,可配置 fallbackClass ,并指定fallbackClass里面的方法。 |
fallbackClass |
否 |
存放fallback的类。 对应的处理函数必须static修饰,否则无法解析,其他要求:同fallback。 |
defaultFallback |
否 |
用于通用的 fallback 逻辑。 默认 fallback 函数可以针对所有类型的异常(除了 exceptionsToIgnore 里面排除掉的异常类型)进行处理。若同时配置了 fallback 和 defaultFallback,以fallback为准。函数要求: 1.返回类型与原方法一致 2.方法参数列表为空,或者有一个 Throwable 类型的参数。 3.默认需要和原方法在同一个类中。若希望使用其他类的函数,可配置 fallbackClass ,并指定 fallbackClass 里面的方法。 |
exceptionsToIgnore |
否 |
指定排除掉哪些异常。 排除的异常不会计入异常统计,也不会进入fallback逻辑,而是原样抛出。 |
exceptionsToTrace |
否 |
需要trace的异常 |
注意
fallback只用来处理与Java逻辑异常相关的兜底
。比如:NullPointerException、ArrayIndexOutOfBoundsException 等Java代码中的异常,fallback 指定的兜底方法便会生效。
blockHandler 只用来处理 与 Sentinel 配置有关的兜底
。比如:配置某资源 QPS =1,当 QPS >1 时,blockHandler 指定的兜底方法便会生效。
- 弱
blockHandler
和fallbackHandler
都进行了配置,则被限流降级而抛出BlockException时只会进入blockHandler处理逻辑。
- 使用
exceptionsTolgnore
属性,来 指定某些异常不执行兜底方法,直接显示错误信息
。配置 ArithmeticException 异常不走兜底方法。java.lang.ArithmeticException: / by zero
,便不会再执行兜底方法,直接显示错误信息给前台页面。
- 使用
defaultFallback
来指定通用的 fallback 兜底方法。
- 如果当前业务配置有
defaultFallback
和 fallback
两个属性,则优先执行 fallback
指定的方法。
- 如果
fallback
指定的方法不存在,还会执行 defaultFallback
指定的方法。