【微服务|Sentinel】流控规则概述|针对来源|流控模式详解<直接 关联 链路>

我们可在簇点链路进行流控设置,点开相关资源的流控按钮即可进行流控相关设置。
在这里插入图片描述

流控规则一览

1. 资源名

  1. 唯一名称,默认请求路径

2. 针对来源

  1. Sentinel可以针对调用者进行限流,默认为default(不区分来源)

3. 阙值类型

  1. QPS:每秒请求数,当前调用该api的QPS到达阈值的时候进行限流
  2. 线程数:当调用该api的线程数到达阈值的时候,进行限流

4. 是否集群

  1. 是否为集群

5. 流控模式

  1. 直接:当api大达到限流条件时,直接限流
  2. 关联:当关联的资源到达阈值,就限流自己
  3. 链路:只记录指定路上的流量,指定资源从入口资源进来的流量,如果达到阈值,就进行限流,api级别的限流

6. 流控效果

  1. 直接失败
  2. Warm Up
  3. 排队等待

在这里插入图片描述

针对来源

介绍

此处的针对来源,对应限流规则中的 limitApp 字段。

限流规则中的 limitApp 字段用于根据调用方进行流量控制。该字段的值有以下三种选项,分别对应不同的场景:

  1. default:表示不区分调用者,来自任何调用者的请求都将进行限流统计。如果这个资源名的调用总和超过了这条规则定义的阈值,则触发限流。
  2. {some_origin_name}:表示针对特定的调用者,只有来自这个调用者的请求才会进行流量控制。例如 NodeA 配置了一条针对调用者caller1的规则,那么当且仅当来自 caller1 对 NodeA 的请求才会触发流量控制。
  3. other:表示针对除 {some_origin_name} 以外的其余调用方的流量进行流量控制。例如,资源NodeA配置了一条针对调用者 caller1 的限流规则,同时又配置了一条调用者为 other 的规则,那么任意来自非 caller1 对 NodeA 的调用,都不能超过 other 这条规则定义的阈值。

同一个资源名可以配置多条规则,规则的生效顺序为:{some_origin_name} > other > default

实现该功能步骤

如何设置这个针对来源,需要我们自己实现api接口。

  1. 步骤一:
    实现com.alibaba.csp.sentinel.adapter.servlet.callback.RequestOriginParser

    import com.alibaba.csp.sentinel.adapter.servlet.callback.RequestOriginParser;
    import javax.servlet.http.HttpServletRequest;
    
    /**
     * @author issavior
     */
    public class MyRequestOriginParser implements RequestOriginParser {
          
          
    
        @Override
        public String parseOrigin(HttpServletRequest httpServletRequest) {
          
          
    
            // 请求头的key,根据key值获取value值,此value值会赋予origin,完成流控规则校验
            return httpServletRequest.getHeader("service-name");
        }
    }
    
    
  2. 步骤二:
    放进配置类,使其生效

    
    import com.alibaba.csp.sentinel.adapter.servlet.CommonFilter;
    import com.alibaba.csp.sentinel.adapter.servlet.callback.WebCallbackManager;
    import org.springframework.boot.web.servlet.FilterRegistrationBean;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    /**
     * @author issavior
     */
    @Configuration
    public class SentinelConfig {
          
          
    
        @Bean
        public FilterRegistrationBean webCallbackFilter() {
          
          
    
            FilterRegistrationBean bean = new FilterRegistrationBean();
            bean.setFilter(new CommonFilter());
            bean.addUrlPatterns("/*");
            bean.addInitParameter(CommonFilter.WEB_CONTEXT_UNIFY, "false");
            bean.setName("sentinelFilter");
            bean.setOrder(-1);
    
            WebCallbackManager.setRequestOriginParser(new MyRequestOriginParser());
            return bean;
        }
    }
    
    

控制台实现

在这里插入图片描述

通过代码定义流量控制规则

理解上面规则的定义之后,我们可以通过调用 FlowRuleManager.loadRules() 方法来用硬编码的方式定义流量控制规则

    @GetMapping("/{id}")
    @SentinelResource("test")
    public String producerById(@PathVariable(value = "id") String id) {
    
    
        sentinelRule();
        ProducerVO producerVO = new ProducerVO();
        producerVO.setId(id);
        producerVO.setPort(UUID.randomUUID().toString());

        return producerVO.toString();
    }

    /**
     * 硬编码级别的流控方案
     * 我们可以将限流规则写在代码里,再添加到规则管理器中,但这种方式不为推崇,扩展性以及灵活性极差。
     */
    private void sentinelRule() {
    
    

        List<FlowRule> rules = new ArrayList<>();

        FlowRule rule = new FlowRule();
        rule.setResource("/producer/{id}");
        rule.setCount(1);
        rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
        rule.setLimitApp("ossa-service-producer");

        rules.add(rule);

        FlowRuleManager.loadRules(rules);
    }

测试

在这里插入图片描述

部分源码

com.alibaba.csp.sentinel.slots.block.flow.FlowRuleChecker#selectNodeByRequesterAndStrategy

在这里插入图片描述

流控模式

流控模式之关联

当指定接口关联的接口达到限流条件时,将对指定接口开启限流。

此方式适合做应用让步,比如对数据库同一个字段的读操作和写操作存在争抢,读的速度过高会影响写得速度,写的速度过高会影响读的速度。如果放任读写操作争抢资源,则争抢本身带来的开销会降低整体的吞吐量。可使用关联限流来避免具有关联关系的资源之间过度的争抢。

举例来说,read_db 和 write_db 这两个资源分别代表数据库读写,我们可以给 read_db 设置限流规则来达到写优先的目的:设置 FlowRule.strategy 为 RuleConstant.RELATE 同时设置 FlowRule.ref_identity 为 write_db。这样当写库操作过于频繁时,读数据的请求会被限流。

再比如说,支付的服务已经快要崩盘了,这是不是需要对订单服务给予一定措施,那是不是需要以订单接口作为资源名,支付接口作为关联资源。当支付接口达到一定的时候,就需要对订单接口限流,以保证支付接口的顺畅。

测试案例:当接口/testconfig每秒访问量达到1时,/product 接口将被限流无法访问。

在这里插入图片描述

流控模式之链路

链路流控模式:
针对资源链路上的接口进行限流,例如:A、B两个接口都调用某一资源C,A->C、B->C可以看成两个简单的链路,此时可以针对C配置链路限流,比如限制A调用C,而B调用C则不受影响,它的功能有点类似于针对 来源配置项,而链路流控是针对上级接口,它的粒度 更细。

测试案例:两个测试接口,调用同一service资源,对其中一个调用链路进行流控

在这里插入图片描述

资源

在这里插入图片描述
在这里插入图片描述 引述官网的话,解释上面的操作。

NodeSelectorSlot 中记录了资源之间的调用链路,这些资源通过调用关系,相互之间构成一棵调用树。这棵树的根节点是一个名字为 machine-root 的虚拟节点,调用链的入口都是这个虚节点的子节点。

一棵典型的调用树如下图所示:

在这里插入图片描述
上图中来自入口 Entrance1 和 Entrance2 的请求都调用到了资源 NodeA,Sentinel 允许只根据某个入口的统计信息对资源限流。比如我们可以设置 FlowRule.strategy 为 RuleConstant.CHAIN,同时设置 FlowRule.ref_identity 为 Entrance1 来表示只有从入口 Entrance1 的调用才会记录到 NodeA 的限流统计当中,而对来自 Entrance2 的调用漠不关心。

调用链的入口是通过 API 方法 ContextUtil.enter(name) 定义的。

流控效果

快速失败

默认配置项, 直接失败,抛出异常,不做任何额外的处理,是最简单的效果。

在这里插入图片描述

Warm Up

预热/冷启动:
当流量突然增大的时候,我们常常会希望系统从空闲状态到繁忙状态的切换的时间长一些。即如果系统在此之前长期处于空闲的状态,我们希望处理请求的数量是缓步的增多,经过预期的时间以后,到达系统处理请求个数的最大值。Warm Up(冷启动,预热)模式就是为了实现这个目的的。

这个场景主要用于启动需要额外开销的场景,例如建立数据库连接等。

根据codeFactor(冷加载因子,默认为3)的值,即请求 QPS 从 threshold / 3 开始,经预热时长逐渐升至设定的 QPS 阈值 。

测试案例:
对/product资源进行链路线路,设置阈值为10。则刚访问此接口时,实际限流阈值为10/3,即为3,也就是刚开始的时候阈值只有3,当经过10s后,阈值才慢慢提高到10。

在这里插入图片描述

排队等待

让请求以均匀的速度通过,单机阈值为每秒通过数量,其余的排队等待; 它还会让设置一个超时时间,当请求超过超时间时间还未处理,则会被丢弃。

这种方式主要用于处理间隔性突发的流量,例如消息队列。想象一下这样的场景,在某一秒有大量的请求到来,而接下来的几秒则处于空闲状态,我们希望系统能够在接下来的空闲期间逐渐处理这些请求,而不是在第一秒直接拒绝多余的请求。

测试案例
对service资源进行链路线路,设置阈值为10。设置流控效果为排队等候,每秒10次请求时,再有请求就排队等候,等待超时时间为10000ms, 超时过后,请求将被踢出排队队列,返回限流异常。

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/CSDN_SAVIOR/article/details/125430556
今日推荐