目录
定义资源
默认对Web请求进行流量控制,如何自定义的去保护一个资源呢?
方式一:主流框架的默认适配
方式二:抛出异常的方式定义资源
方式三:返回布尔值方式定义资源
方式四:注解方式定义资源
方式五:异步调用支持
一、注解方式定义资源 - @SentinelResource
按资源名称限流+后续处理
启动Nacos成功,启动Sentinel成功。
业务类:
@RestController
public class RateLimitController {
@GetMapping("/byResource")
@SentinelResource(value = "byResource", blockHandler = "handleException")
public CommonResult byResource() {
return new CommonResult(200, "按资源名称限流测试OK", new Payment(2020L, "serial001"));
}
public CommonResult handleException(BlockException exception) {
return new CommonResult(444, exception.getClass().getCanonicalName() + "\t 服务不可用");
}
}
启动项目。
配置流控规则:
访问接口:http://localhost:8401/byResource 测试规则是否生效。
测试完后,把项目停了。
发现,规则没了!!
Sentinel控制台,流控规则是临时的!
按照Url地址限流+后续处理
0
上面兜底方法面临的问题
客户自定义限流处理逻辑
解决上述问题。
自定义限流处理类:
public class CustomerBlockHandler {
public static CommonResult handleException1(BlockException exception) {
return new CommonResult(2020, "自定义限流处理信息....CustomerBlockHandler....1");
}
public static CommonResult handleException2(BlockException exception) {
return new CommonResult(2020, "自定义限流处理信息....CustomerBlockHandler....2");
}
}
业务代码:
@GetMapping("/rateLimit/customerBlockHandler")
@SentinelResource(value = "customerBlockHandler", //资源名
blockHandlerClass = CustomerBlockHandler.class, //自定义限流处理类
blockHandler = "handleException2") //使用自定义限流处理类中的哪一个方法
public CommonResult customerBlockHandler()
{
return new CommonResult(200,"按客戶自定义",new Payment(2020L,"serial003"));
}
启动微服务后,先调用一次:触发一下懒加载。
http://localhost:8401/rateLimit/customerBlockHandler
添加流控规则:
快速访问:http://localhost:8401/rateLimit/customerBlockHandler
更多注解属性说明
Sentinel其实可以通过代码的方式去配置各种规则,不过不推荐
Sentinel主要有三个核心API
- SphU定义资源
- Tracer定义统计
- ContextUtil定义了上下文
二、抛出异常的方式定义资源
// 1.5.0 版本开始可以利用 try-with-resources 特性(使用有限制)
// 资源名可使用任意有业务语义的字符串,比如方法名、接口名或其它可唯一标识的字符串。
try (Entry entry = SphU.entry("resourceName")) {
// 被保护的业务逻辑
// do something here...
} catch (BlockException ex) {
// 资源访问阻止,被限流或被降级
// 在此处进行相应的处理操作
}
注意:若 entry 的时候传入了热点参数,那么 exit 的时候也一定要带上对应的参数(exit(count, args)),否则可能会有统计错误。这个时候不能使用 try-with-resources 的方式。另外通过 Tracer.trace(ex) 来统计异常信息时,由于 try-with-resources 语法中 catch 调用顺序的问题,会导致无法正确统计异常数,因此统计异常信息时也不能在 try-with-resources 的 catch 块中调用 Tracer.trace(ex)。
Entry entry = null;
// 务必保证 finally 会被执行
try {
// 资源名可使用任意有业务语义的字符串,注意数目不能太多(超过 1K),超出几千请作为参数传入而不要直接作为资源名
// EntryType 代表流量类型(inbound/outbound),其中系统规则只对 IN 类型的埋点生效
entry = SphU.entry("自定义资源名");
// 被保护的业务逻辑
// do something...
} catch (BlockException ex) {
// 资源访问阻止,被限流或被降级
// 进行相应的处理操作
} catch (Exception ex) {
// 若需要配置降级规则,需要通过这种方式记录业务异常
Tracer.traceEntry(ex, entry);
} finally {
// 务必保证 exit,务必保证每个 entry 与 exit 配对
if (entry != null) {
entry.exit();
}
}
热点参数埋点示例:
Entry entry = null;
try {
// 若需要配置例外项,则传入的参数只支持基本类型。
// EntryType 代表流量类型,其中系统规则只对 IN 类型的埋点生效
// count 大多数情况都填 1,代表统计为一次调用。
entry = SphU.entry(resourceName, EntryType.IN, 1, paramA, paramB);
// Your logic here.
} catch (BlockException ex) {
// Handle request rejection.
} finally {
// 注意:exit 的时候也一定要带上对应的参数,否则可能会有统计错误。
if (entry != null) {
entry.exit(1, paramA, paramB);
}
}
网关流控
在网关模块里,依赖:
<!--sentinel与gateway的自动配置-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
<version>2.2.0.RELEASE</version>
</dependency>
1.7.1
会有一个API
管理,1.7.2
没有
网关路由的id
就是上面的API
名称
一、添加流控规则
- 间隔表示统计的时间窗口,单位是秒,至少是1秒。上面的表示2秒统计一次
- burst:应对突发请求时额外允许的请求数量。
针对请求属性设置流控规则:
二、自定义网关流控响应
@Configuration
public class SentinelGatewayConfig {
public SentinelGatewayConfig(){
GatewayCallbackManager.setBlockHandler(new BlockRequestHandler() {
/**
* 网关限流了请求,就会调用此回调
* @param serverWebExchange
* @param throwable
* @return
*/
@Override
public Mono<ServerResponse> handleRequest(ServerWebExchange serverWebExchange, Throwable throwable) {
R error = R.error(BizCodeEnum.TOO_MANY_REQUEST.getCode(), BizCodeEnum.TOO_MANY_REQUEST.getMessage());
String string = JSON.toJSONString(error);
return ServerResponse.ok().body(Mono.just(string), String.class);
}
});
}
}