美文网首页Sentinel
Sentinel资源节点树构成

Sentinel资源节点树构成

作者: 晴天哥_王志 | 来源:发表于2021-06-13 21:40 被阅读0次

系列

相同资源名场景分析

Entry entry = null;

try {
    entry = SphU.entry("abc");
    entry = SphU.entry("abc");
} catch (BlockException e1) {

} finally {
    if (entry != null) {
        entry.exit();
    }
}

创建Context

public class ContextUtil {

    protected static Context trueEnter(String name, String origin) {
        Context context = contextHolder.get();
        if (context == null) {
            Map<String, DefaultNode> localCacheNameMap = contextNameNodeMap;
            DefaultNode node = localCacheNameMap.get(name);
            if (node == null) {
                if (localCacheNameMap.size() > Constants.MAX_CONTEXT_NAME_SIZE) {
                    setNullContext();
                    return NULL_CONTEXT;
                } else {
                    LOCK.lock();
                    try {
                        node = contextNameNodeMap.get(name);
                        if (node == null) {
                            if (contextNameNodeMap.size() > Constants.MAX_CONTEXT_NAME_SIZE) {
                                setNullContext();
                                return NULL_CONTEXT;
                            } else {
                                node = new EntranceNode(new StringResourceWrapper(name, EntryType.IN), null);
                                // Add entrance node.
                                Constants.ROOT.addChild(node);

                                Map<String, DefaultNode> newMap = new HashMap<>(contextNameNodeMap.size() + 1);
                                newMap.putAll(contextNameNodeMap);
                                newMap.put(name, node);
                                contextNameNodeMap = newMap;
                            }
                        }
                    } finally {
                        LOCK.unlock();
                    }
                }
            }
            // 这里的node设置的是Context的EntranceNode
            context = new Context(node, name);
            context.setOrigin(origin);
            contextHolder.set(context);
        }

        return context;
    }
}
  • 首先在ThreadLocal获取,获取不到就创建,不然就返回
  • 然后再Map中根据ContextName找一个Node
  • 没有找到Node就加锁的方式,创建一个EntranceNode,然后放入Map中
  • 创建Context,设置node,name,origin,再放入ThreadLocal中

第一次创建Entry

Entry e = new CtEntry(resourceWrapper, chain, context);

class CtEntry extends Entry {
    protected Entry parent = null;
    protected Entry child = null;

    protected ProcessorSlot<Object> chain;
    protected Context context;
    protected LinkedList<BiConsumer<Context, Entry>> exitHandlers;

    CtEntry(ResourceWrapper resourceWrapper, ProcessorSlot<Object> chain, Context context) {
        super(resourceWrapper);
        this.chain = chain;
        this.context = context;

        setUpEntryFor(context);
    }

    private void setUpEntryFor(Context context) {
        // The entry should not be associated to NullContext.
        if (context instanceof NullContext) {
            return;
        }
        // 首次返回为null
        this.parent = context.getCurEntry();
        if (parent != null) {
            ((CtEntry) parent).child = this;
        }
        // 设置Context的curEntry为当前的CtEntry
        context.setCurEntry(this);
    }
}

第一次执行NodeSelectorSlot

@Spi(isSingleton = false, order = Constants.ORDER_NODE_SELECTOR_SLOT)
public class NodeSelectorSlot extends AbstractLinkedProcessorSlot<Object> {

    private volatile Map<String, DefaultNode> map = new HashMap<String, DefaultNode>(10);

    @Override
    public void entry(Context context, ResourceWrapper resourceWrapper, Object obj, int count, boolean prioritized, Object... args)
        throws Throwable {

        DefaultNode node = map.get(context.getName());
        if (node == null) {
            synchronized (this) {
                node = map.get(context.getName());
                if (node == null) {
                    node = new DefaultNode(resourceWrapper, null);
                    HashMap<String, DefaultNode> cacheMap = new HashMap<String, DefaultNode>(map.size());
                    cacheMap.putAll(map);
                    cacheMap.put(context.getName(), node);
                    map = cacheMap;
                    // 构建调用树,添加entranceNode的子节点
                    ((DefaultNode) context.getLastNode()).addChild(node);
                }

            }
        }
        // 设置Context的当前节点
        context.setCurNode(node);
        fireEntry(context, resourceWrapper, node, count, prioritized, args);
    }
}

public class Context {
    private final String name;
    private DefaultNode entranceNode;
    private Entry curEntry;
    private String origin = "";
    private final boolean async;

    public Node getLastNode() {
        if (curEntry != null && curEntry.getLastNode() != null) {
            return curEntry.getLastNode();
        } else {
            return entranceNode;
        }
    }

    public Context setCurNode(Node node) {
        this.curEntry.setCurNode(node);
        return this;
    }
}

第二次创建Entry

Entry e = new CtEntry(resourceWrapper, chain, context);

class CtEntry extends Entry {
    protected Entry parent = null;
    protected Entry child = null;

    protected ProcessorSlot<Object> chain;
    protected Context context;
    protected LinkedList<BiConsumer<Context, Entry>> exitHandlers;

    CtEntry(ResourceWrapper resourceWrapper, ProcessorSlot<Object> chain, Context context) {
        super(resourceWrapper);
        this.chain = chain;
        this.context = context;

        setUpEntryFor(context);
    }

    private void setUpEntryFor(Context context) {
        // The entry should not be associated to NullContext.
        if (context instanceof NullContext) {
            return;
        }
        // 首次返回为null
        this.parent = context.getCurEntry();
        if (parent != null) {
            ((CtEntry) parent).child = this;
        }
        // 设置Context的curEntry为当前的CtEntry
        context.setCurEntry(this);
    }
}

第二次执行NodeSelectorSlot

@Spi(isSingleton = false, order = Constants.ORDER_NODE_SELECTOR_SLOT)
public class NodeSelectorSlot extends AbstractLinkedProcessorSlot<Object> {

    private volatile Map<String, DefaultNode> map = new HashMap<String, DefaultNode>(10);

    @Override
    public void entry(Context context, ResourceWrapper resourceWrapper, Object obj, int count, boolean prioritized, Object... args)
        throws Throwable {

        DefaultNode node = map.get(context.getName());
        if (node == null) {
            synchronized (this) {
                node = map.get(context.getName());
                if (node == null) {
                    node = new DefaultNode(resourceWrapper, null);
                    HashMap<String, DefaultNode> cacheMap = new HashMap<String, DefaultNode>(map.size());
                    cacheMap.putAll(map);
                    cacheMap.put(context.getName(), node);
                    map = cacheMap;
                    // 构建调用树,添加entranceNode的子节点
                    ((DefaultNode) context.getLastNode()).addChild(node);
                }

            }
        }
        // 设置Context的当前节点
        context.setCurNode(node);
        fireEntry(context, resourceWrapper, node, count, prioritized, args);
    }
}

public class Context {
    private final String name;
    private DefaultNode entranceNode;
    private Entry curEntry;
    private String origin = "";

    private final boolean async;
    public Node getLastNode() {
        if (curEntry != null && curEntry.getLastNode() != null) {
            return curEntry.getLastNode();
        } else {
            return entranceNode;
        }
    }

    public Context setCurNode(Node node) {
        this.curEntry.setCurNode(node);
        return this;
    }
}

不同资源名场景分析

Entry entry = null;

try {
    entry = SphU.entry("abc");
    entry = SphU.entry("abcd");
} catch (BlockException e1) {

} finally {
    if (entry != null) {
        entry.exit();
    }
}

第一次创建Entry

Entry e = new CtEntry(resourceWrapper, chain, context);

class CtEntry extends Entry {
    protected Entry parent = null;
    protected Entry child = null;

    protected ProcessorSlot<Object> chain;
    protected Context context;
    protected LinkedList<BiConsumer<Context, Entry>> exitHandlers;

    CtEntry(ResourceWrapper resourceWrapper, ProcessorSlot<Object> chain, Context context) {
        super(resourceWrapper);
        this.chain = chain;
        this.context = context;

        setUpEntryFor(context);
    }

    private void setUpEntryFor(Context context) {
        // The entry should not be associated to NullContext.
        if (context instanceof NullContext) {
            return;
        }
        // 首次返回为null
        this.parent = context.getCurEntry();
        if (parent != null) {
            ((CtEntry) parent).child = this;
        }
        // 设置Context的curEntry为当前的CtEntry
        context.setCurEntry(this);
    }
}

第一次执行NodeSelectorSlot

@Spi(isSingleton = false, order = Constants.ORDER_NODE_SELECTOR_SLOT)
public class NodeSelectorSlot extends AbstractLinkedProcessorSlot<Object> {

    private volatile Map<String, DefaultNode> map = new HashMap<String, DefaultNode>(10);

    @Override
    public void entry(Context context, ResourceWrapper resourceWrapper, Object obj, int count, boolean prioritized, Object... args)
        throws Throwable {

        DefaultNode node = map.get(context.getName());
        if (node == null) {
            synchronized (this) {
                node = map.get(context.getName());
                if (node == null) {
                    node = new DefaultNode(resourceWrapper, null);
                    HashMap<String, DefaultNode> cacheMap = new HashMap<String, DefaultNode>(map.size());
                    cacheMap.putAll(map);
                    cacheMap.put(context.getName(), node);
                    map = cacheMap;
                    // 构建调用树,添加entranceNode的子节点
                    ((DefaultNode) context.getLastNode()).addChild(node);
                }

            }
        }
        // 设置Context的当前节点
        context.setCurNode(node);
        fireEntry(context, resourceWrapper, node, count, prioritized, args);
    }
}

public class Context {
    private final String name;
    private DefaultNode entranceNode;
    private Entry curEntry;
    private String origin = "";

    private final boolean async;
    public Node getLastNode() {
        if (curEntry != null && curEntry.getLastNode() != null) {
            return curEntry.getLastNode();
        } else {
            return entranceNode;
        }
    }

    public Context setCurNode(Node node) {
        this.curEntry.setCurNode(node);
        return this;
    }
}

第二次创建Entry

Entry e = new CtEntry(resourceWrapper, chain, context);

class CtEntry extends Entry {
    protected Entry parent = null;
    protected Entry child = null;

    protected ProcessorSlot<Object> chain;
    protected Context context;
    protected LinkedList<BiConsumer<Context, Entry>> exitHandlers;

    CtEntry(ResourceWrapper resourceWrapper, ProcessorSlot<Object> chain, Context context) {
        super(resourceWrapper);
        this.chain = chain;
        this.context = context;

        setUpEntryFor(context);
    }

    private void setUpEntryFor(Context context) {
        // The entry should not be associated to NullContext.
        if (context instanceof NullContext) {
            return;
        }
        // 首次返回为null
        this.parent = context.getCurEntry();
        if (parent != null) {
            ((CtEntry) parent).child = this;
        }
        // 设置Context的curEntry为当前的CtEntry
        context.setCurEntry(this);
    }
}

第二次执行NodeSelectorSlot

@Spi(isSingleton = false, order = Constants.ORDER_NODE_SELECTOR_SLOT)
public class NodeSelectorSlot extends AbstractLinkedProcessorSlot<Object> {

    private volatile Map<String, DefaultNode> map = new HashMap<String, DefaultNode>(10);

    @Override
    public void entry(Context context, ResourceWrapper resourceWrapper, Object obj, int count, boolean prioritized, Object... args)
        throws Throwable {

        DefaultNode node = map.get(context.getName());
        if (node == null) {
            synchronized (this) {
                node = map.get(context.getName());
                if (node == null) {
                    node = new DefaultNode(resourceWrapper, null);
                    HashMap<String, DefaultNode> cacheMap = new HashMap<String, DefaultNode>(map.size());
                    cacheMap.putAll(map);
                    cacheMap.put(context.getName(), node);
                    map = cacheMap;
                    // 构建调用树,第一次添加entranceNode的子节点
                    // 第二次添加到当前节点的父节点当中
                    ((DefaultNode) context.getLastNode()).addChild(node);
                }

            }
        }
        // 设置Context的当前节点
        context.setCurNode(node);
        fireEntry(context, resourceWrapper, node, count, prioritized, args);
    }
}

public class Context {
    private final String name;
    private DefaultNode entranceNode;
    private Entry curEntry;
    private String origin = "";

    private final boolean async;
    public Node getLastNode() {
        if (curEntry != null && curEntry.getLastNode() != null) {
            return curEntry.getLastNode();
        } else {
            return entranceNode;
        }
    }

    public Context setCurNode(Node node) {
        this.curEntry.setCurNode(node);
        return this;
    }
}

class CtEntry extends Entry {

    protected Entry parent = null;
    protected Entry child = null;

    @Override
    public Node getLastNode() {
        return parent == null ? null : parent.getCurNode();
    }
}
  • 因为资源名不同所以对应的职责链条,因此NodeSelectorSlot会重新创建DefaultNode。


相关文章

  • Sentinel资源节点树构成

    系列 Sentinel流程介绍[https://www.jianshu.com/p/059aaf9492b1] S...

  • 2018-03-24 树

    树由根节点和子节点构成,每个节点及其分支的所有节点构成一个树,由子节点延伸出来的树,称为子树。每个子节点的分支的数...

  • 一文图解二叉树面试题,现在懂了吗?

    一、树 & 二叉树 树是由节点和边构成,储存元素的集合。节点分根节点、父节点和子节点的概念。 如图:树深=4; 5...

  • 一文图解二叉树面试题

    一、树 & 二叉树 树是由节点和边构成,储存元素的集合。节点分根节点、父节点和子节点的概念。 如图:树深=4; 5...

  • 16.Sentinel概念和功能

    Sentinel得概念和功能 基本概念 资源资源就是Sentinel要保护的东西资源是Sentinel的关键概念。...

  • Redis-Sentinel客户端的实现原理和使用方法

    实现原理: 1、客户端遍历Sentinel节点集合,获取一个可用的Sentinel节点(可以ping通的节点)2、...

  • JS常用API合集-节点篇

    节点 Dom树由节点构成,节点分为多种类型,又有不同的方法 Document节点 document是documen...

  • Redis哨兵模式

    Redis哨兵比主从复制多了 sentinel 节点,当主节点出现故障的时候,有 sentinel 自动完成故障发...

  • 数据结构4、树 Tree

    一、定义 树,实际上是图的一种。 树是由节点构成的数据结构: 每棵树都有一个根节点。 根节点有0个或多个子节点。 ...

  • 数据结构线索二叉树

    线索二叉树构成 线索化的节点 实现

网友评论

    本文标题:Sentinel资源节点树构成

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