sentinel服务治理, 一般是使用@SentinelResource注解配置,
那么可以大胆猜想一下实现应该是AOP
接下来看源码来验证猜想
一、 pom引入sentinel依赖jar
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
二、 找到starter-alibaba-sentinel, 找到spring.factoried的SentinelAutoConfiguration类
三、 在SentinelAutoConfiguration类里, 我们看到了一个*Aspect的类 -> SentinelResourceAspect
@Aspect
public class SentinelResourceAspect extends AbstractSentinelAspectSupport {
@Pointcut("@annotation(com.alibaba.csp.sentinel.annotation.SentinelResource)")
public void sentinelResourceAnnotationPointcut() {
}
@Around("sentinelResourceAnnotationPointcut()")
public Object invokeResourceWithSentinel(ProceedingJoinPoint pjp) throws Throwable {
Method originMethod = resolveMethod(pjp);
...
try {
entry = SphU.entry(resourceName, resourceType, entryType, pjp.getArgs());
// 对aop有了解的, 都知道pjp.proceed()是执行本身逻辑,
// 那么上面这一行SphU.entry 一定就是服务治理逻辑的那一层了
Object result = pjp.proceed();
return result;
} catch (BlockException ex) {
return handleBlockException(pjp, annotation, ex);
} catch (Throwable ex) {
Class<? extends Throwable>[] exceptionsToIgnore = annotation.exceptionsToIgnore();
// The ignore list will be checked first.
if (exceptionsToIgnore.length > 0 && exceptionBelongsTo(ex, exceptionsToIgnore)) {
throw ex;
}
if (exceptionBelongsTo(ex, annotation.exceptionsToTrace())) {
traceException(ex);
return handleFallback(pjp, annotation, ex);
}
// No fallback function can handle the exception, so throw it out.
throw ex;
} finally {
if (entry != null) {
entry.exit(1, pjp.getArgs());
}
}
}
}
四、 构建SlotChain链路
SphU entry
public static Entry entry(String name, int resourceType, EntryType trafficType, Object[] args)
throws BlockException {
// new CtSph().entryWithType
return Env.sph.entryWithType(name, resourceType, trafficType, 1, args);
}
CtSph entryWithPriority
private Entry entryWithPriority(ResourceWrapper resourceWrapper, int count, boolean prioritized, Object... args) throws BlockException {
Context context = ContextUtil.getContext();
...
// 核心 链路模式
// 构建服务治理一系列类的chain
// 构建会触发DefaultSlotChainBuilder.build方法 如下
ProcessorSlot<Object> chain = lookProcessChain(resourceWrapper);
/*
* Means amount of resources (slot chain) exceeds {@link Constants.MAX_SLOT_CHAIN_SIZE},
* so no rule checking will be done.
*/
if (chain == null) {
return new CtEntry(resourceWrapper, null, context);
}
Entry e = new CtEntry(resourceWrapper, chain, context);
try {
chain.entry(context, resourceWrapper, null, count, prioritized, args);
} catch (BlockException e1) {
e.exit(count, args);
throw e1;
} catch (Throwable e1) {
// This should not happen, unless there are errors existing in Sentinel internal.
RecordLog.info("Sentinel unexpected exception", e1);
}
return e;
}
public class DefaultSlotChainBuilder implements SlotChainBuilder {
@Override
public ProcessorSlotChain build() {
ProcessorSlotChain chain = new DefaultProcessorSlotChain();
// 实例化所有实现了ProcessorSlot的类
// 截图如下
List<ProcessorSlot> sortedSlotList = SpiLoader.loadPrototypeInstanceListSorted(ProcessorSlot.class);
for (ProcessorSlot slot : sortedSlotList) {
if (!(slot instanceof AbstractLinkedProcessorSlot)) {
RecordLog.warn("The ProcessorSlot(" + slot.getClass().getCanonicalName() + ") is not an instance of AbstractLinkedProcessorSlot, can't be added into ProcessorSlotChain");
continue;
}
chain.addLast((AbstractLinkedProcessorSlot<?>) slot);
}
return chain;
}
}
Slot中的@SpiOrder() 从小到大 构建出了一个SlotChain
流控 - FlowSlot
日志 - logSlot
统计 - StatisticSlot(相应时间等等)
系统cpu相关控制 - SystemSlot
服务降级 - DegradeSlot
权限 - AuthoritySlot
五、 逻辑方法的finally exit方法
看一个服务降级DegradeSlot的exit方法
onRequestComplete()
calss ExceptionCircuitBreaker
@Override
private void handleStateChangeWhenThresholdExceeded(Throwable error) {
if (currentState.get() == State.OPEN) {
return;
}
// HALF_OPEN 半开
if (currentState.get() == State.HALF_OPEN) {
// In detecting request
if (error == null) {
//如果不报错 直接关闭断路器
fromHalfOpenToClose();
} else {
// 设置snapshotValue
fromHalfOpenToOpen(1.0d);
}
return;
}
List<SimpleErrorCounter> counters = stat.values();
long errCount = 0;
long totalCount = 0;
for (SimpleErrorCounter counter : counters) {
errCount += counter.errorCount.sum();
totalCount += counter.totalCount.sum();
}
if (totalCount < minRequestAmount) {
return;
}
double curCount = errCount;
if (strategy == DEGRADE_GRADE_EXCEPTION_RATIO) {
// Use errorRatio
curCount = errCount * 1.0d / totalCount;
}
// 错误率大于阈值 打开断路器
if (curCount > threshold) {
transformToOpen(curCount);
}
}