【Sentinel】限流,熔断等具体流程分析

基于sentinel 1.8.6
在这里插入图片描述
从sentinel-dashboard来看,sentinel主要提供了流控,熔断,热点,系统规则,授权规则等。

针对http请求的数据监控以及规则限制的适配,可以参考sentinel-spring-webmvc-adapter以及sentinel-web-servlet-adapter
具体的实现类

com.alibaba.csp.sentinel.adapter.servlet.CommonFilter
com.alibaba.csp.sentinel.adapter.spring.webmvc.SentinelWebInterceptor

一个是基于spring的HandlerInterceptor,一个是基于servlet的Filter。

com.alibaba.csp.sentinel.adapter.servlet.CommonFilter为例
在这里插入图片描述
init,doFilter,destory这三个方法分别对应初始化,逻辑处理,执行完处理的逻辑,重点放在doFilter()方法。

@Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
    
    
        HttpServletRequest sRequest = (HttpServletRequest) request;
        Entry urlEntry = null;

        try {
    
    
            String target = FilterUtil.filterTarget(sRequest);
            // Clean and unify the URL.
            // For REST APIs, you have to clean the URL (e.g. `/foo/1` and `/foo/2` -> `/foo/:id`), or
            // the amount of context and resources will exceed the threshold.
            UrlCleaner urlCleaner = WebCallbackManager.getUrlCleaner();
            if (urlCleaner != null) {
    
    
                target = urlCleaner.clean(target);
            }

            // If you intend to exclude some URLs, you can convert the URLs to the empty string ""
            // in the UrlCleaner implementation.
            if (!StringUtil.isEmpty(target)) {
    
    
            	//解析来源
                String origin = parseOrigin(sRequest);
                String contextName = webContextUnify ? WebServletConfig.WEB_SERVLET_CONTEXT_NAME : target;
                //设置上下文
                ContextUtil.enter(contextName, origin);
				//执行sentinel一系列规则,各种校验。
                if (httpMethodSpecify) {
    
    
                    // Add HTTP method prefix if necessary.
                    String pathWithHttpMethod = sRequest.getMethod().toUpperCase() + COLON + target;
                    urlEntry = SphU.entry(pathWithHttpMethod, ResourceTypeConstants.COMMON_WEB, EntryType.IN);
                } else {
    
    
                    urlEntry = SphU.entry(target, ResourceTypeConstants.COMMON_WEB, EntryType.IN);
                }
            }
            //真正的执行请求
            chain.doFilter(request, response);
        } catch (BlockException e) {
    
    
            HttpServletResponse sResponse = (HttpServletResponse) response;
            // Return the block page, or redirect to another URL.
            WebCallbackManager.getUrlBlockHandler().blocked(sRequest, sResponse, e);
        } catch (IOException | ServletException | RuntimeException e2) {
    
    
            Tracer.traceEntry(e2, urlEntry);
            throw e2;
        } finally {
    
    
            if (urlEntry != null) {
    
    
                urlEntry.exit();
            }
            ContextUtil.exit();
        }
    }

主要看下在执行真正的chain.doFilter()执行前,sentinel都做了些什么?

com.alibaba.csp.sentinel.SphU#entry(java.lang.String, int, com.alibaba.csp.sentinel.EntryType)
com.alibaba.csp.sentinel.CtSph#entryWithPriority(com.alibaba.csp.sentinel.slotchain.ResourceWrapper, int, boolean, java.lang.Object...)
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 = InternalContextUtil.internalEnter(Constants.CONTEXT_DEFAULT_NAME);
        }

        // Global switch is close, no rule checking will do.
        if (!Constants.ON) {
    
    
            return new CtEntry(resourceWrapper, null, context);
        }
		//初始化流控规则的chain链
        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;
    }
 ProcessorSlot<Object> chain = lookProcessChain(resourceWrapper); 这个方法会初始化默认的规则校验链,说白了就是流控,熔断...这些规则,我该怎么一个一个的进行校验。
com.alibaba.csp.sentinel.slotchain.SlotChainProvider#newSlotChain
com.alibaba.csp.sentinel.spi.SpiLoader#loadFirstInstanceOrDefault

在这里插入图片描述

sentinel基于SPI的方式实现了一个默认的处理链,接口为com.alibaba.csp.sentinel.slotchain.SlotChainBuilder的实现
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
处理链的每一个slot都是实现ProcessorSolt。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
以熔断为例,她是一个扩展的spi接口,并且设置了优先级,所以初始化后的规则校验链如下图所示
在这里插入图片描述
到目前为止,大致清楚了,我们在sentinel设置了一些类型的规则,规则校验的顺序是什么?怎么实现,如何加载的应该已经很清晰了。

再回到com.alibaba.csp.sentinel.CtSph#entryWithPriority(com.alibaba.csp.sentinel.slotchain.ResourceWrapper, int, boolean, java.lang.Object...)这个方法中,执行的具体方法为com.alibaba.csp.sentinel.slotchain.ProcessorSlot#entry

以流控校验为例
在这里插入图片描述
执行flowSlot的entry方法时,会从上下文中获取该资源的统计信息。并与当前类型的规则进行比较,并更新进统计信息。
统计信息存储在StatisticNode里。包括当前资源名,执行了通过多少次,拒绝多少次等信息。

com.alibaba.csp.sentinel.node.StatisticNode

以上大致就是http请求,sentinel处理的流程,对于dubbo请求,参考类

com.alibaba.csp.sentinel.adapter.dubbo.SentinelDubboProviderFilter
com.alibaba.csp.sentinel.adapter.dubbo.SentinelDubboConsumerFilter

dubbo支持应用本身作为消费者以及生产者的调用信息的统计。

猜你喜欢

转载自blog.csdn.net/qq_31426247/article/details/128321096