原理回顾
在前面的《Sentinel实战与原理剖析》这一篇文章中,我们分析了Sentinel的原理,这里再回顾一下。
Sentinel底层实现了责任链模式,把不同的slot(槽)串联成一个chain(链),每一个slot对应一个规则的处理。当我们调用SphU.entry(…)方法时,Sentinel就会以责任链模式的方式逐一调用chain中的slot去进行规则校验,一旦某个slot校验不通过,那么就终止,所有slot都检验通过才算校验通过,最后entry方法会返回一个Entry对象。
我们在硬编码模式下,通过某种方式在服务启动时往Sentinel注册一些规则,比如以下初始化流控规则这样:
/**
* @author huangjunyi
* @date 2024/4/8 19:06
* @desc
*/
@Component
public class FlowRuleInit {
@PostConstruct
public void init() {
initFlowRules();
}
// 初始化流控规则,也可以在控制台中配置
private static void initFlowRules(){
List<FlowRule> rules = new ArrayList<>();
FlowRule rule = new FlowRule();
rule.setResource("hello");
rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
rule.setCount(2);
rules.add(rule);
FlowRuleManager.loadRules(rules);
}
}
我们往FlowRuleManager注册了List<FlowRule>,List<FlowRule>里面的每一个FlowRule对应就是一个流控规则。
于是FlowSlot在进行规则校验时,就会调用FlowRuleManager.getFlowRules(String resource)方法根据资源名resource取出注册到FlowRuleManager的所有与当前资源名对应的流控规则,然后对每一个FlowRule进行检验。
还有处理熔断规则的DegradeRuleManager与DegradeSlot,以及处理授权规则的AuthorityRuleManager与AuthoritySlot也是如此。
源码解析
chain的构建
SphU#entry(String):
public static Entry entry(String name) throws BlockException {
return Env.sph.entry(name, EntryType.OUT, 1, OBJECTS0);
}
SphU#entry(String)一路进去到CtSph#entryWithPriority(ResourceWrapper, int, boolean, Object…)
private Entry entryWithPriority(ResourceWrapper resourceWrapper, int count, boolean prioritized, Object... args)
throws BlockException {
...
// 构建chain(如果已经构建过,会从缓存取)
ProcessorSlot<Object> chain = lookProcessChain(resourceWrapper);
...
Entry e = new CtEntry(resourceWrapper, chain, context