sentinel笔记 NodeSelectorSlot,ClusterBuilderSlot

2021/11/3 14:39:44

本文主要是介绍sentinel笔记 NodeSelectorSlot,ClusterBuilderSlot,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

 

 

NodeSelectorSlot 负责为资源的首次访问创建 DefaultNode,以及维护 Context.curNode 和调用树,

 一次调用链路上出现多次调用SphU#entry,则每次调用生成的CEntry最终会变成双向链表,存储在Context中。

NodeSelectorSlot 被放在 ProcessorSlotChain 链表的第一个位置,这是因为后续的 ProcessorSlot 都需要依赖这个 ProcessorSlot。

 public class NodeSelectorSlot extends AbstractLinkedProcessorSlot<Object> {
    // Context 的 name -> 资源的 DefaultNode
    private volatile Map<String, DefaultNode> map = new HashMap<>(10);
    
    // 入口方法
    @Override
    public void entry(Context context, ResourceWrapper resourceWrapper, Object obj, int count, boolean prioritized, Object... args) throws Throwable {
        // 使用 Context 的名称作为 key 缓存资源的 DefaultNode
        DefaultNode node = map.get(context.getName());
        if (node == null) {
            synchronized (this) {
                node = map.get(context.getName());
                if (node == null) {
                    // 为资源创建 DefaultNode
                    node = new DefaultNode(resourceWrapper, null);
                    // 替换 map
                    HashMap<String, DefaultNode> cacheMap = new HashMap<>(map.size());
                    cacheMap.putAll(map);
                    cacheMap.put(context.getName(), node);
                    map = cacheMap;
                    // 绑定调用树
                    ((DefaultNode) context.getLastNode()).addChild(node);
                }
            }
        }
        // 替换 Context 的 curNode 为当前 DefaultNode
        context.setCurNode(node);
        fireEntry(context, resourceWrapper, node, count, prioritized, args);
    }

    // 出口方法什么也不做
    @Override
    public void exit(Context context, ResourceWrapper resourceWrapper, int count, Object... args) {
        fireExit(context, resourceWrapper, count, args);
    }
}

 

NodeSelectorSlot#map的作用:

一个资源对应一个slotchain,一个slotchain下记录不同的context创建的DefaultNode.
Sentinel 会为同一资源 ID 创建多少个 DefaultNode 取决于有多少个调用链使用其作为入口资源,直白点就是同一资源存在多少个 DefaultNode 取决于 Context.name 有多少种不同取值,这就是为什么说一个资源可能有多个 DefaultNode 的原因。

举个例子,

对同一支付接口,我们需要使用 Spring MVC 暴露给前端访问,同时也可能会使用 Dubbo 暴露给其它内部服务调用。Sentinel 的 Web MVC 适配器在调用链路入口创建名为“sentinel_spring_web_context”的 Context,与 Sentinel 的 Dubbo 适配器调用 ContextUtil#enter 方法创建的 Context 名称不同。针对这种情况,我们可以实现只限制 Spring MVC 进来的流量,也就是限制前端发起接口调用的 QPS、并行占用的线程数等。

 

spring-webmvc默认拦截使用的context是由类com.alibaba.csp.sentinel.adapter.spring.webmvc.AbstractSentinelInterceptor来实现的,默认值是sentinel_spring_web_context 。

 

context+resource确认唯一的DeafultNode。

一个context对应一个EntranceNode,

一个Resouce对应一个ClusterNode,并且对应一个ProcessorSlotChain, ,

每个ProcessorSlotChain包含一个Map, 存储本resource下,context与DefaultNode的关系。

同一个context下存储一个Entry调用链, 每个Entry执行接受后调用entry.exit(1),目的是退出本Node,并且返回Parent CEntry,

每个StatisticsNode还有Map,包含Node的origin信息,用来对不同来源的Node做区分统计。

 

node关系表

 



这篇关于sentinel笔记 NodeSelectorSlot,ClusterBuilderSlot的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程