天天看点

Ali sentinel 代码分析-基础及概念

阿里Sentinel 基本概念主要包括下图内容:

总体说明

Ali sentinel 代码分析-基础及概念

从定义和运行两种态势,可以分为定义态:

  • rule,规则,每个规则定义都关联一个资源名称,一个资源可以定义多个rule
  • ruleManager ,规则管理
  • slot,承载规则的卡槽
  • Chain,多个slot组成的链,在老版本 Chain是hard code写死的,1.8.1使用order 来定义,便于加入自定义slot

运行态:

  • Entry :入口,入口会指定资源名称
  • Chain及slot: 执行链
  • Context: 上下文,贯穿整个执行过程
  • Node: 保留各种数据,如一定时间内的qps
  • Metric:各种指标,保存在node上,注意node还有非metric数据
  • Resource: 被Entry保护的资源,可以通俗理解为所有rule通过后要执行的代码

Resource

可以理解为Entry(后面会讲)获取成功要要执行的方法或者代码 ,一般和Entry绑定在一起,如:

try (Entry entry = SphU.entry("HelloWorld")) {
            // 被保护的逻辑
            System.out.println("hello world");
	} catch (BlockException ex) {
            // 处理被流控的逻辑
	    System.out.println("blocked!");
	}
           

或者annotation写法:

@SentinelResource("HelloWorld")
public void helloWorld() {
    // 资源中的逻辑
    System.out.println("hello world");
}
  
           

以上代码中的"HelloWorld" 被称为资源名称,用于关联下面提到的slot及chain,也可以理解为通过resource name进行规则关联。

目前只有String和method两种resource,对应的类定义信息如下:

28   * @author qinan.qn
   29   */
   30: public class MethodResourceWrapper extends ResourceWrapper {
   31  
   32      private final transient Method method;

 
   25   * @author jialiang.linjl
   26   */
   27: public class StringResourceWrapper extends ResourceWrapper {
   28  
   29      public StringResourceWrapper(String name, EntryType e) {
           

Entry

以下为Entry的官方说法:

每一次资源调用都会创建一个 Entry。Entry 包含了资源名、curNode(当前统计节点)、originNode(来源统计节点)等信息。

CtEntry 为普通的 Entry,在调用 SphU.entry(xxx) 的时候创建。特性:Linked entry within current context(内部维护着 parent 和 child)

需要注意的一点:CtEntry 构造函数中会做调用链的变换,即将当前 Entry 接到传入 Context 的调用链路上(setUpEntryFor)。

资源调用结束时需要 entry.exit()。exit 操作会过一遍 slot chain exit,恢复调用栈,exit context 然后清空 entry 中的 context 防止重复调用。

通俗来说,Entry就是进入sentinel的一系列数据(如CPU、QPS)获取及规则判断,如果这些规则判断都通过了,就执行资源函数或者代码。

Entry的执行过程就对应则一个或者多个规则集合体,有两个实现类:

SphU.entry() 获取失败返回异常
SphO.entry()  返回true或者false
           

这两个类的最终实现都是通过类CtSph实现的,可以参考如下代码

public static boolean entry(String name, EntryType trafficType, int batchCount, Object... args) {
        try {
            Env.sph.entry(name, trafficType, batchCount, args);
        } catch (BlockException e) {
            return false;
        } catch (Throwable e) {
            RecordLog.warn("SphO fatal error", e);
            return true;
        }
        return true;
    }

public class Env {

    public static final Sph sph = new CtSph();

    static {
        // If init fails, the process will exit.
        InitExecutor.doInit();
    }

}
           

chain及slot

没有Entry在执行过程会去寻找对应的Chain

ProcessorSlot<Object> lookProcessChain(ResourceWrapper resourceWrapper) {
        ProcessorSlotChain chain = chainMap.get(resourceWrapper);
        if (chain == null) {
            synchronized (LOCK) {
                chain = chainMap.get(resourceWrapper);
                if (chain == null) {
                    // Entry size limit.
                    if (chainMap.size() >= Constants.MAX_SLOT_CHAIN_SIZE) {
                        return null;
                    }

                    chain = SlotChainProvider.newSlotChain();
                    Map<ResourceWrapper, ProcessorSlotChain> newMap = new HashMap<ResourceWrapper, ProcessorSlotChain>(
                        chainMap.size() + 1);
                    newMap.putAll(chainMap);
                    newMap.put(resourceWrapper, chain);
                    chainMap = newMap;
                }
            }
        }
        return chain;
    }
           

然后执行Chain上的slot(数据获取或者检测类),默认chain 的build 类是com.alibaba.csp.sentinel.slots.DefaultSlotChainBuilder

可以参考sentinel-demo-slot-chain-spi 进行修改

sentinel 自带的主要slot如下

  • NodeSelectorSlot 负责收集资源的路径,并将这些资源的调用路径,以树状结构存储起来,用于根据调用路径来限流降级;
  • ClusterBuilderSlot 则用于存储资源的统计信息以及调用者信息,例如该资源的 RT, QPS, thread count等等,这些信息将用作为多维度限流,降级的依据;
  • StatisticSlot 则用于记录、统计不同纬度的 runtime 指标监控信息
  • FlowSlot 则用于根据预设的限流规则以及前面 slot 统计的状态,来进行流量控制;
  • AuthoritySlot则根据配置的黑白名单和调用来源信息,来做黑白名单控制;
  • DegradeSlot 则通过统计信息以及预设的规则,来做熔断降级
  • SystemSlot 则通过系统的状态,例如 load1 等,来控制总的入口流量;

Rule

Chain是内部执行,外部不能直接定义,外部定义是通过rules模式来实现的,可以参考sentinel-demo-basic 下的这四个子目录下的代码

Ali sentinel 代码分析-基础及概念

这四个目录对应四中规则:

  • DegradeRule
  • AuthorityRule
  • FlowRule
  • SystemRule

一个资源可以有以上4种规则中的多种进行合并判断。

Context

context中维护着当前调用链的元数据

SphU.entry() 或 SphO.entry() 都需要在一个 context 中执行,如果没有当前执行时还没有 context,那么框架会使用默认的 context,默认的 context 是通过 MyContextUtil.myEnter() 创建的

Node

Node 中保存了资源的实时统计数据,例如:passQps,blockQps,rt等实时数据。正是有了这些统计数据后, Sentinel 才能进行限流、降级等一系列的操作。

Metric

Metric 是 Sentinel 中用来进行实时数据统计的度量接口,node就是通过metric来进行数据统计的。而metric本身也并没有统计的能力,他也是通过Window来进行统计的。

继续阅读