sentinel源码分析
2022-02-16 22:12:48 3 举报
sentinel源码全流程
作者其他创作
大纲/内容
重置慢调用和总调用 统计次数为0
checkFlow
DegradeRuleManager.getCircuitBreakers(r.getName())
从当前时间窗口里统计指标数据
SlotChainProvider.newSlotChain()
记录日志
LogSlot
获取相关资源的校验规则
从时间窗口数组里获取当前时间计算下标对应的old 时间窗口 一开始是null的
next
fireEntry
node.addPassRequest(count)
first
检查通过降级规则
调用异常数及比例判断逻辑
获得所有的资源规则
return;
总调用+1
计算时间窗口里的统计数据
ExceptionCircuitBreaker#onRequestComplete
0
true如果调用超时时间依然大于rt时阙值,则把断路器打开
DegradeSlot
SystemSlot
SPIOrder值越小排在越前
node.passQps()
慢调用比例降级判断逻辑
检查
windowStart == old.windowStart()
counters[event.ordinal()].add(n);
BlockException
SPI加载slot chain加载sentinel-core包下的META-INF\\service里对应的文件里的类
counter.totalCount.add(1);
@SentinelResource
DefaultController#canPass
流控规则
ClusterBuilderSlot
DefaultProcessorSlotChain
断路器处在半打开状态currentState.get() == State.HALF_OPEN一般都会尝试的调用一次
array就是时间窗口数组
正常情况下添加当前调用线程数
断路器是关闭状态currentState.get() == State.CLOSED
添加调用完成数和调用执行时间RT
rt > maxAllowedRt
减少当前调用线程数
计算当前时间窗口数组下标
rollingCounterInSecond.pass() / rollingCounterInSecond.getWindowIntervalInSec();
是否集群
tryPass
添加当前通过的qps数
抛Throwable
return old;
如果总调用次数小于配置最小请求数,则不修改断路器状态,返回
NodeSelectorSlot
校验资源系统规则
WindowWrap<T> old = array.get(idx);
node.decreaseThreadNum()
calculateWindowStart(timeMillis)
null
判断是否集群
调用退出
counter.slowCount.add(1);
node.increaseBlockQps(count);添加blockQps数
获得当前时间对应的时间窗口
重置下次断路器的熔断周期
WarmUpController#canPass
if (currentRatio > maxSlowRequestRatio) { transformToOpen(currentRatio); }
double currentRatio = slowCount * 1.0d / totalCount;
单机限流
CtSph#entryWithPriority
node.addRtAndSuccess
做一些其他规则检查
StatisticSlot
断路器 打开currentState==OPEN
断路器关闭currentState==CLOSED
circuitBreaker.onRequestComplete(context)
调用完处理断路器状态
ServiceLoader.load(clazz)
添加异常数量
构建slot责任链
resetStat();
windowStart old.windowStart()如果依据当前时间算出来的时间窗口起始时间大于old时间窗口的起始时间。则将old时间窗口重置,变为当前时间应该落入的时间窗口
RateLimiterController#canPass
passLocalCheck
this.clusterNode.increaseThreadNum();
ruleProvider.apply(resource.getName())
Warm Up
return true
构建资源的slot校验链条每个资源都有自己独立的校验链条有点类似Netty的pipeline
计算当前时间窗口的起始时间位置
//添加调用次数slowCount和调用总数 slowCount += counter.slowCount.sum(); totalCount += counter.totalCount.sum();
wrap.value().addPass(count);
快速失败
滑动时间窗口算法
rollingCounterInSecond.addPass(count);
return retryTimeoutArrived() && fromOpenToHalfOpen(context);
spring-cloud-starter-alibaba-sentinel.jar里的spring.factories文件里的SentinelAutoConfiguration
添加当前调用线程数
令牌桶算法
1000
时间窗口数组
排队等待
逐个调用slot校验链条里的每一个校验规则的entry逻辑
对资源逐条校验每个规则
TimeUtil.currentTimeMillis() >= nextRetryTimestamp
拦截
if (totalCount < minRequestAmount) { return; }
AuthoritySlot
按顺序加载
时间窗口里的请求数据统计实际是放在一个counter数组里不同的下标代表不同的数据统计指标
fromHalfOpenToOpen(1.0d)
end
this.clusterNode.addPassRequest(count)
fromHalfOpenToClose()
FlowSlot
负责收集资源的路径,并将这些资源的调用路径,以树状结构存储起来,用于根据调用路径来限流降级
DegradeSlot.exit()
if (curCount + acquireCount > count) { return false;}
@Bean
performChecking
this.windowLengthInMs = intervalInMs / sampleCount; this.intervalInMs = intervalInMs; this.sampleCount = sampleCount; this.array = new AtomicReferenceArray<>(sampleCount);
slotChainBuilder.build()(DefaultSlotChainBuilder)
对资源准逐条校验每个规则
WindowWrap<MetricBucket> wrap = data.currentWindow();
this.clusterNode.increaseBlockQps(count);
构建责任链
handleStateChangeWhenThresholdExceeded(rt)
return false 检验不通过
抛BlockException
新生成一个时间窗口,并放入时间窗口数组里
updateNextRetryTimestamp();
ResponseTimeCircuitBreaker#onRequestComplete
@AspectSentinelResourceAspect
node.increaseThreadNum()
false则把断路器改为关闭
添加pass类型的请求数
avgUsedTokens(node)
calculateTimeIdx(timeMillis);
recordCompleteFor
断路器是打开状态currentState.get() == State.OPEN
校验资源授权规则
SpiLoader.loadPrototypeInstanceListSorted(ProcessorSlot.class)
构建entry对象
如果慢调用比例大于配置,则把断路器打开
Throwable
500
lookProcessChain(resourceWrapper)
如果rt maxAllowedRt如果请求响应时间超过最大rt时间把慢调用次数+1
计算慢调用比例
漏桶算法
添加时间窗口的请求通过数
canPassCheck
1
0 条评论
回复 删除
下一页