SpringCloudAlibaba—Sentinel流控实现源码流程
2022-10-03 13:56:18 9 举报
登录查看完整内容
SpringCloudAlibaba—Sentinel流控实现源码流程
作者其他创作
大纲/内容
try{}Catch记录退出异常日志
调用下一个nodeexit()
切点 ,对标注有@SentinelResource进行动态代理,环绕通知@Pointcut(\"@annotation(com.alibaba.csp.sentinel.annotation.SentinelResource)\") public void sentinelResourceAnnotationPointcut() {}
执行下一个节点fireEntry()
配置的预热时长内,缓慢到达阈值QPS
校验系统规则,校验QPS、CPU、线程数、响应时间、LOAD SystemRuleManager.checkSystem(resourceWrapper);
true
SPI 加载的Slot文件
执行受保护的方法 Object result = pjp.proceed();
排队熔断时长是否大于设置规则中的熔断时长retryTimeoutArrived()
SpringCloudAlibaba 整合Sentinel使用到了SpringAOP,通过切面对资源进行保护
finally最终执行
获取所有降级规则List<CircuitBreaker> circuitBreakers = DegradeRuleManager.getCircuitBreakers(r.getName());
ClusterBuilderSlot
校验不通过抛出 FlowException异常
流控效果:排队等待
chain = SlotChainProvider.newSlotChain();
将slot放入链表中 for (ProcessorSlot slot : sortedSlotList){ chain.addLast((AbstractLinkedProcessorSlot<?>) slot);}
DefaultController.canPass()
流控异常BlockException ex
用于保存特定上下文中特定资源名称的统计信息 DefaultNode node = map.get(context.getName()); context.setCurNode(node);
流控效果:快速失败
entry()
加载所有ProcessorSlotServiceLoader<T> serviceLoader = ServiceLoaderUtil.getServiceLoader(clazz);
调用slotChain链条的退出方法资源重置
组装链条 end.setNext(protocolProcessor); end = protocolProcessor;
半开改为打开状态fromHalfOpenToOpen
设置集群节点统计信息clusterNode
addLast()
LogSlot
校验通过执行下一个节点fireEntry()
注入切面SentinelResourceAspect(),是整合sentinel的核心类@Bean@ConditionalOnMissingBeanpublic SentinelResourceAspect sentinelResourceAspect() { return new SentinelResourceAspect();}
创建链条ProcessorSlotChain chain = new DefaultProcessorSlotChain();
直接执行下一个节点fireEntry()
半开改为关闭状态fromHalfOpenToClose();
节点执行完成回来后,对执行的阈值信息进行统计。如:通过线程数、失败数等
退出调用
校验通过
当前阈值数量+1 > 配置规则中的阈值,触发保护,校验不通过。if (curCount + acquireCount > count){ return false}return true
如果校验不通过
校验流控规则checker.checkFlow()
执行链条的下一个节点fireEntry()
校验通过return true
设置熔断器状态
canPassCheck()
如果熔断器处于打开状态 if (currentState.get() == State.OPEN) { return retryTimeoutArrived() && fromOpenToHalfOpen(context); }
校验不通过抛出SystemBlockException异常
如果是打开状态,不做任何处理if (currentState.get() == State.OPEN) { return; }
创建资源保护执行链条slotChainBuilder.build();
SystemSlot
FlowSlot
通过spi机制从文件中加载所有的规则处理slotList<ProcessorSlot> sortedSlotList = SpiLoader.loadPrototypeInstanceListSorted(ProcessorSlot.class);
所有请求在超时时间类排队执行
业务异常Throwable ex
获取当前阈值int curCount = avgUsedTokens(node);
try开启异常捕获
chain
资源保护流控方法invokeResourceWithSentinel()
从Sentinel的自动配置类开始
获取所有的鉴权黑白名单Set<AuthorityRule> rules = authorityRules.get(resource.getName());
cb.tryPass(context)
使用SPI机制,从文件中加载slotChainBuilder slotChainBuilder = SpiLoader.loadFirstInstanceOrDefault
firstAbstractLinkedProcessorSlot
校验不通过retrun false
捕获到异常执行catch
newSlotChain()
ProcessorSlotChain
1.loadPrototypeInstanceListSorted()
error != null有异常
try{}Catch记录异常日志信息
for (CircuitBreaker cb : circuitBreakers){ if (!cb.tryPass(context)){ throw new DegradeException() }}
DegradeSlot
false
空方法直接调用下一个nodeexit()
如果当前开关时关闭状态,直接校验通过 if (currentState.get() == State.CLOSED) { return true; }
将熔断断器打开状态改为半开状态fromOpenToHalfOpen(context)
2
整个调用没有异常curEntry.getBlockError() == null)
如果是半开状态if (currentState.get() == State.HALF_OPEN)
根据设置规则,选择获取QPS数或者获取线程数return grade == RuleConstant.FLOW_GRADE_THREAD ? node.curThreadNum() : (int)(node.passQps());
获取该资源的所有rules Collection<FlowRule> rules = ruleProvider.apply(resource.getName());
StatisticSlot
AuthoritySlot
RateLimiterController.canPass()
WarmUpController.canPass()
预热只有QPSlong passQps = (long) node.passQps();
SentinelAutoConfiguration
构建资源保护规则执行链条ProcessorSlot<Object> chain = lookProcessChain(resourceWrapper);
chain链条创建完成后,按照链条顺序依次执行
记录异常统计信息
error == null没有异常
流控效果:Warm Up
NodeSelectorSlot
0 条评论
回复 删除
下一页