sentinel设计思想

首先咱们看一下Sentinel项目的整个结构:version:1.6.0app

* sentinel-core 核心模块,限流、降级、系统保护等都在这里实现
* sentinel-dashboard 控制台模块,能够对链接上的sentinel客户端实现可视化的管理
* sentinel-transport 传输模块,提供了基本的监控服务端和客户端的API接口,以及一些基于不一样库的实现
* sentinel-extension 扩展模块,主要对DataSource进行了部分扩展实现
* sentinel-adapter 适配器模块,主要实现了对一些常见框架的适配
* sentinel-demo 样例模块,可参考怎么使用sentinel进行限流、降级等
* sentinel-benchmark 基准测试模块,对核心代码的精确性提供基准测试

底层原理:sentinel 入口是 SphU.entry建立框架

private Entry entryWithPriority(ResourceWrapper resourceWrapper, int count, boolean prioritized, Object... args)

    throws BlockException {

    Context context = ContextUtil.getContext();

    if (context instanceof NullContext) {

        // The {@link NullContext} indicates that the amount of context has exceeded the threshold,

        // so here init the entry only. No rule checking will be done.

        return new CtEntry(resourceWrapper, null, context);

    }

  

  

    if (context == null) {

        // Using default context.

        context = MyContextUtil.myEnter(Constants.CONTEXT\_DEFAULT\_NAME, "", resourceWrapper.getType());

    }

  

  

    // Global switch is close, no rule checking will do.

    if (!Constants.ON) {

        return new CtEntry(resourceWrapper, null, context);

    }

  

  

    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;

}

这个方法能够分为如下几个部分:less

* 1.对参数和全局配置项作检测,若是不符合,不会再进行后面的限流检测,不然进入下面的检测流程。
* 2.根据包装过的资源对象获取对应的SlotChain
* 3.执行SlotChain的entry方法

    * 3.1.若是SlotChain的entry方法抛出了BlockException,则将该异常继续向上抛出
    * 3.2.若是SlotChain的entry方法正常执行了,则最后会将该entry对象返回
* 4.若是上层方法捕获了BlockException,则说明请求被限流了,不然请求能正常执行

其中比较重要的是第二、3两个步骤,咱们来分解一下这两个步骤。建立SlotChain默认的实现类为 DefaultProcessorSlotChain:链表实现的责任链测试

private Entry entryWithPriority(ResourceWrapper resourceWrapper, int count, boolean prioritized, Object... args)

    throws BlockException {

    Context context = ContextUtil.getContext();

    if (context instanceof NullContext) {

        // The {@link NullContext} indicates that the amount of context has exceeded the threshold,

        // so here init the entry only. No rule checking will be done.

        return new CtEntry(resourceWrapper, null, context);

    }

  

  

    if (context == null) {

        // Using default context.

        context = MyContextUtil.myEnter(Constants.CONTEXT\_DEFAULT\_NAME, "", resourceWrapper.getType());

    }

  

  

    // Global switch is close, no rule checking will do.

    if (!Constants.ON) {

        return new CtEntry(resourceWrapper, null, context);

    }

  

  

    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;

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

执行完业务逻辑处理后,调用了fireEntry()方法,由此触发了下一个节点的entry方法。此时咱们就知道了sentinel的责任链就是这样传递的:每一个Slot节点执行完本身的业务后,会调用fireEntry来触发下一个节点的entry方法。ui

相关文章
相关标签/搜索