Sentinel-NodeSelectorSlot

NodeSelectorSlot解析

在理解这一章前,可以先阅读sentinel整体架构可能了解起来更有帮助。

 

在NodeSelectorSlot中维护这变量  private volatile Map<String, DefaultNode> map = new HashMap<String, DefaultNode>(10);

相同资源共享一个chain,也就使用同一个NodeSelectorSlot对象。其中key表示context name 而value表示DefaultNode,说明对于相同的资源名称的不同contextName中各自有一个defaultNode,并添加到数结构中。

代码如下:

    @Override
    public void entry(Context context, ResourceWrapper resourceWrapper, Object obj, int count, boolean prioritized, Object... args)
        throws Throwable {
        /*
         * It's interesting that we use context name rather resource name as the map key.
         *
         * Remember that same resource({@link ResourceWrapper#equals(Object)}) will share
         * the same {@link ProcessorSlotChain} globally, no matter in which context. So if
         * code goes into {@link #entry(Context, ResourceWrapper, DefaultNode, int, Object...)},
         * the resource name must be same but context name may not.
         *
         * If we use {@link com.alibaba.csp.sentinel.SphU#entry(String resource)} to
         * enter same resource in different context, using context name as map key can
         * distinguish the same resource. In this case, multiple {@link DefaultNode}s will be created
         * of the same resource name, for every distinct context (different context name) each.
         *
         * Consider another question. One resource may have multiple {@link DefaultNode},
         * so what is the fastest way to get total statistics of the same resource?
         * The answer is all {@link DefaultNode}s with same resource name share one
         * {@link ClusterNode}. See {@link ClusterBuilderSlot} for detail.
         */
        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;
                    // Build invocation tree
                    // 这边会继续构建调用树
                    /**
                     * 相同资源的DefaultNode 不同context name的 都会添加到对应的entranceNode上,
                     * 如果context name相同  资源名称也相同   则  DefaultNode在多线程内共享
                     */
                    ((DefaultNode)context.getLastNode()).addChild(node);
                }

            }
        }

        // 设置context的当前node为当前资源的的defaultNode
        context.setCurNode(node);
        // 触发下一个slot
        fireEntry(context, resourceWrapper, node, count, prioritized, args);
    }

 

posted @ 2021-09-15 22:18  gaojy  阅读(121)  评论(0编辑  收藏  举报