美文网首页
【sentinel】深入浅出之原理篇SlotChain

【sentinel】深入浅出之原理篇SlotChain

作者: 一滴水的坚持 | 来源:发表于2019-03-17 14:59 被阅读0次

    最近在负责做网关类系统,需要考虑做限流熔断功能,基于QPS,基于线程数,对于集群,单机做限流,熔断,而Sentinel能满足我的所有需求,配置接入方便,设计上很适合做扩展。
    关于sentinel的详细介绍逅弈大佬已经有详细的博客介绍了,mark一下(https://www.jianshu.com/u/51121bddcd2a)。
    我再简单摘要一下。

    diagram.png
    在整个限流熔断的过程中,实际是基于slotChain来实现,而 slotchain内部则是使用链表来实现。
    
    public interface ProcessorSlot<T> {
    
        void entry(Context context, ResourceWrapper resourceWrapper, T param, int count, boolean prioritized,
                   Object... args) throws Throwable;
        void fireEntry(Context context, ResourceWrapper resourceWrapper, Object obj, int count, boolean prioritized,
                       Object... args) throws Throwable;
        void exit(Context context, ResourceWrapper resourceWrapper, int count, Object... args);
    
        void fireExit(Context context, ResourceWrapper resourceWrapper, int count, Object... args);
    }
    
    
    public abstract class AbstractLinkedProcessorSlot<T> implements ProcessorSlot<T> {
    
        private AbstractLinkedProcessorSlot<?> next = null;
    
        @Override
        public void fireEntry(Context context, ResourceWrapper resourceWrapper, Object obj, int count, boolean prioritized, Object... args)
            throws Throwable {
            if (next != null) {
                next.transformEntry(context, resourceWrapper, obj, count, prioritized, args);
            }
        }
        @SuppressWarnings("unchecked")
        void transformEntry(Context context, ResourceWrapper resourceWrapper, Object o, int count, boolean prioritized, Object... args)
            throws Throwable {
            T t = (T)o;
            entry(context, resourceWrapper, t, count, prioritized, args);
        }
        @Override
        public void fireExit(Context context, ResourceWrapper resourceWrapper, int count, Object... args) {
            if (next != null) {
                next.exit(context, resourceWrapper, count, args);
            }
        }
        public AbstractLinkedProcessorSlot<?> getNext() {
            return next;
        }
        public void setNext(AbstractLinkedProcessorSlot<?> next) {
            this.next = next;
        }
    }
    

    可以看到AbstractLinkedProcessorSlot为一个Slot节点,通过setNext指定下一个Slot节点,通过 fireEntry()方法,调用下一个节点的transformEntry()最终调用到下一个Slot节点的entry方法,本身的结构类似于

    clsss Slot {
      Slot next;
    }
    

    这不就是大学时数据结构常提到的链表结构。
    再来看看 ProcessorSlotChainDefaultProcessorSlotChain

    public abstract class ProcessorSlotChain extends AbstractLinkedProcessorSlot<Object> {
        //添加头节点
        public abstract void addFirst(AbstractLinkedProcessorSlot<?> protocolProcessor);
        //添加下一个节点
        public abstract void addLast(AbstractLinkedProcessorSlot<?> protocolProcessor);
    }
    
    
    public class DefaultProcessorSlotChain extends ProcessorSlotChain {
    
        AbstractLinkedProcessorSlot<?> first = new AbstractLinkedProcessorSlot<Object>() {
    
            @Override
            public void entry(Context context, ResourceWrapper resourceWrapper, Object t, int count, boolean prioritized, Object... args)
                throws Throwable {
                super.fireEntry(context, resourceWrapper, t, count, prioritized, args);
            }
    
            @Override
            public void exit(Context context, ResourceWrapper resourceWrapper, int count, Object... args) {
                super.fireExit(context, resourceWrapper, count, args);
            }
    
        };
        AbstractLinkedProcessorSlot<?> end = first;
    
        @Override
        public void addFirst(AbstractLinkedProcessorSlot<?> protocolProcessor) {
            protocolProcessor.setNext(first.getNext());
            first.setNext(protocolProcessor);
            if (end == first) {
                end = protocolProcessor;
            }
        }
    
        @Override
        public void addLast(AbstractLinkedProcessorSlot<?> protocolProcessor) {
            end.setNext(protocolProcessor);
            end = protocolProcessor;
        }
    
    
        @Override
        public void setNext(AbstractLinkedProcessorSlot<?> next) {
            addLast(next);
        }
    
        @Override
        public AbstractLinkedProcessorSlot<?> getNext() {
            return first.getNext();
        }
    
        @Override
        public void entry(Context context, ResourceWrapper resourceWrapper, Object t, int count, boolean prioritized, Object... args)
            throws Throwable {
            first.transformEntry(context, resourceWrapper, t, count, prioritized, args);
        }
    
        @Override
        public void exit(Context context, ResourceWrapper resourceWrapper, int count, Object... args) {
            first.exit(context, resourceWrapper, count, args);
        }
    }
    

    可以看到, DefaultProcessorSlotChain实质是指定头节点FirstSlotendSnot的链表。就如下面结构 :

    public Class Chain{
      Slot first;
      Slot end;
    }
    

    而在初始化 SlotChain的时候,实质添加顺序是这样子滴

    public ProcessorSlotChain build() {
        ProcessorSlotChain chain = new DefaultProcessorSlotChain();
        chain.addLast(new NodeSelectorSlot());
        chain.addLast(new ClusterBuilderSlot());
        chain.addLast(new LogSlot());
        chain.addLast(new StatisticSlot());
        chain.addLast(new SystemSlot());
        chain.addLast(new AuthoritySlot());
        chain.addLast(new FlowSlot());
        chain.addLast(new DegradeSlot());
        return chain;
    }
    

    所以整个SlotChain的结构如下图:


    DefaultProcessorSlotChain

    而具体的熔断限流都是每个Slot的具体职责:

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

    可以看到,我需要的熔断,限流,白名单控制都可以通过配置AuthorizationSlotFlowSlotDegradeSlot实现。

    相关文章

      网友评论

          本文标题:【sentinel】深入浅出之原理篇SlotChain

          本文链接:https://www.haomeiwen.com/subject/jnnymqtx.html