赞
踩
目前Sentinel支持以下五种限流/熔断规则:基于资源限流(FlowRule)、系统自适应限流(SystemRule)、系统熔断降级(DegradeRule)、热点参数限流(ParamFlowRule),sentinel还支持基于授权的限流(AuthorityRule),其父类为AbstractRule
。
另外,Sentinel还支持网关限流,说到底就是Filter限流,控制限流资源范围。其实现原理为为Servlet添加了一个CommonFilter,doFilter方法如下:
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest sRequest = (HttpServletRequest)request; Entry urlEntry = null; try { String target = FilterUtil.filterTarget(sRequest); UrlCleaner urlCleaner = WebCallbackManager.getUrlCleaner(); if (urlCleaner != null) { target = urlCleaner.clean(target); } if (!StringUtil.isEmpty(target)) { String origin = this.parseOrigin(sRequest); String contextName = this.webContextUnify ? "sentinel_web_servlet_context" : target; ContextUtil.enter(contextName, origin); //=============标记请求路径为资源 start=============== if (this.httpMethodSpecify) { String pathWithHttpMethod = sRequest.getMethod().toUpperCase() + ":" + target; urlEntry = SphU.entry(pathWithHttpMethod, 1, EntryType.IN); } else { urlEntry = SphU.entry(target, 1, EntryType.IN); } //=============标记请求路径为资源 end=============== } chain.doFilter(request, response); } catch (BlockException var15) { HttpServletResponse sResponse = (HttpServletResponse)response; WebCallbackManager.getUrlBlockHandler().blocked(sRequest, sResponse, var15); } catch (ServletException | RuntimeException | IOException var16) { Tracer.traceEntry(var16, urlEntry); throw var16; } finally { if (urlEntry != null) { urlEntry.exit(); } ContextUtil.exit(); } }
“资源”在一个系统中是唯一的吗?即不同接口上的资源名称可以重复吗?
答:可以重复。resource相当于是一个分类,可以加在不同的接口上。
相同名称的rule可以加载成功吗?
答:不可以,同一种类型的rule名称应保持唯一,规则会被放到一个Map中,key为resource名称。源码:com.alibaba.csp.sentinel.slots.block.flow.FlowRuleUtil#buildFlowRuleMap(java.util.List<com.alibaba.csp.sentinel.slots.block.flow.FlowRule>, com.alibaba.csp.sentinel.util.function.Function<com.alibaba.csp.sentinel.slots.block.flow.FlowRule,K>, com.alibaba.csp.sentinel.util.function.Predicate<com.alibaba.csp.sentinel.slots.block.flow.FlowRule>, boolean)
一个资源名称,在两个接口上一起使用时,限流统计规则是两个接口一起还是独立计算?
答:独立计算。
是否允许通配的方式批量添加到controller层?
答:可以。具体操作方法见第四节《网关限流》,其原理是基于Filter,请求进来的时候就被标记了资源。
资源定义的方式有很多种,建议通过注解。
通用异常处理方式?
答:平台可以添加统一的异常处理,违反限流规则会抛出FlowException。源码追溯:com.alibaba.csp.sentinel.slots.block.flow.FlowRuleChecker#checkFlow
。
定义规则名称,与实际注解资源不匹配会报错吗?即注解使用了错误的规则。
答:流控失败,且不会报错。
注解使用一定要放在Controller方法上吗?
答:不一定,也可以在Service、工具类中,其本质为抛出了FlowException异常。
设置了全局范围资源点,且在接口上未定义其他资源,那么设置的资源规则、系统规则、降级规则还生效吗?
答:1-资源规则不生效,检查过程是根据资源名称获取规则后再校验的,如图得到的规则未空,实际上是配置了资源规则的。
public void checkFlow(Function<String, Collection<FlowRule>> ruleProvider, ResourceWrapper resource,
Context context, DefaultNode node, int count, boolean prioritized) throws BlockException {
if (ruleProvider == null || resource == null) {
return;
}
Collection<FlowRule> rules = ruleProvider.apply(resource.getName());
if (rules != null) {
for (FlowRule rule : rules) {
if (!canPassCheck(rule, context, node, count, prioritized)) {
throw new FlowException(rule.getLimitApp(), rule);
}
}
}
}
2-系统规则生效。com.alibaba.csp.sentinel.slots.system.SystemRuleManager#checkSystem
3-降级规则不生效。
public static void checkDegrade(ResourceWrapper resource, Context context, DefaultNode node, int count)
throws BlockException {
Set<DegradeRule> rules = degradeRules.get(resource.getName());
if (rules == null) {
return;
}
for (DegradeRule rule : rules) {
if (!rule.passCheck(context, node, count)) {
throw new DegradeException(rule.getLimitApp(), rule);
}
}
}
Sentinel的官网文档已经很是完整了,此处仅是在下做的一些小总结。当然Sentinel的功能还是非常强大的,参数类型也众多,未能测试全面。大家在测试过程中可以使用测试工具JMeter进行测试。
顺便说两句,关于如何学习一个工具有两种思路:
大家在学习的过程中,建议2种方式结合一下。通过测试
来了解
基本功能,通过读源码
来解释测试结果
。这样双管齐下,便可进一步加深理解,学习软件背后的学习思路~
大家如有问题欢迎与我交流~
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。