[Alibaba微服务技术入门]_Sentinel流控规则_第12讲

Sentinel流量控制官方文档:https://github.com/alibaba/Sentinel/wiki/%E6%B5%81%E9%87%8F%E6%8E%A7%E5%88%B6

流量控制概述:

流量控制(flow control),其原理是监控应用流量的 QPS 或并发线程数等指标,当达到指定的阈值时对流量进行控制,以避免被瞬时的流量高峰冲垮,从而保障应用的高可用性

一条限流规则主要由下面几个因素组成,我们可以组合这些元素来实现不同的限流效果:

  • resource:资源名,即限流规则的作用对象
  • count: 限流阈值 grade: 限流阈值类型(QPS 或并发线程数)
  • limitApp: 流控针对的调用来源,若为 default 则不区分调用来源
  • strategy: 调用关系限流策略
  • controlBehavior: 流量控制效果(直接拒绝、Warm Up、匀速排队)

流量控制主要有两种统计类型:

  • 一种是统计并发线程数,当调用该api的线程数达到阈值的时候,进行限流
  • 一种是统计 QPS(每秒钟的请求数量),当调用该api的QPS达到阈值的时候,进行限流

是否集群:不需要集群

流控模式:

  • 直接:api达到限流条件时,直接限流
  • 关联:当关联的资源达到阈值时,就限流自己
  • 链路:只记录指定链路上的流量(指定资源从入口资源进来的流量,如果达到阈值,就进行限流)【api级别的针对来源】

流控效果:

  • 快速失败:直接失败,抛异常
  • Warm Up:根据codeFactor(冷加载因子,默认3)的值,从阈值/codeFactor,经过预热时长,才达到设置的QPS阈值
  • 排队等待:匀速排队,让请求以匀速的速度通过,阈值类型必须设置为QPS,否则无效

流控规则实战:

(一)QPS-直接-快速失败:设置每秒请求数量为 1,那么如果超过这个单机阈值,则sentinel会快速响应失败

 (二)线程数-直接失败:设置处理用户请求的线程数量,如果在一定时间内请求数量增多,而达到线程处理阈值,就会出现流控。比如:设置线程数量为1,需要处理用户请求时间800ms,但是在800ms内出现多个请求需要处理,则sentinel就会进行流控

通过JMeter 进行的线程的并发测试

 (三)流控-关联

  • 概念:当关联的资源达到阈值时,就限流自己
  • 例如:当与A服务关联的资源B达到阀值后,就限流A自己。泛指如果B服务挂掉,A服务就开启对自己的限流
  • 例如:支付接口达到阈值,则就是限流下订单的接口

 我们在FlowLimitController接口中再去定义一个请求 public String playInfo() 方法

package com.liuyangjava.controller;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class FlowLimitController {
    @Value("${server.port}")
    private String port;

    @GetMapping("/sentinel/service")
    public String getInfo() {
        return "sentinel service is running, server port: " + port;
    }
    
    @GetMapping("/sentinel/playInfo")
    public String playInfo() {
        return "sentinel service is playInfo";
    }
}

开始配置流控-关联资源模式,当关联资源 /sentinel/playInfo 的 qps 阀值超过1时,就限流 /sentinel/service 的Rest访问地址

 通过JMeter 进行的线程的并发测试,模拟50个用户,每个用户请求20次,每秒并发5个请求

  • Number of Threads (users):运行的线程数设置,一个线程对应一个模拟用户
  • Ramp-up period (seconds):所有线程在多长时间内开始运行,单位是秒。比如我们设置线程数为 50,此处设置 10 秒,那么每秒就会启动 50 / 10,5 个线程。如果设置为 0 秒,则 50 个线程会立刻启动。如果设置为 100 秒,就会每隔 100 / 50,2 秒 启动 1 个线程
  • Loop Count:迭代次数。可以填写数字指定迭代次数。也可以勾选 Infinite,表示无限迭代,一直运行到测试停止或异常崩溃

通过上面的模拟,当请求达到阈值,则 /sentinel/service 就会对自己进行限流控制

(四)预热(warm up)

当系统长期处于低水位的情况下,当流量突然增加时,直接把系统拉升到高水位可能瞬间把系统压垮。通过"冷启动",让通过的流量缓慢增加,在一定时间内逐渐增加到阈值上限,给冷系统一个预热的时间,避免冷系统被压垮

默认 coldFactor 为 3,即请求 QPS 从 threshold / 3 开始,经预热时长逐渐升至设定的 QPS 阈值 

预热冷启动的文档地址:https://github.com/alibaba/Sentinel/wiki/%E9%99%90%E6%B5%81---%E5%86%B7%E5%90%AF%E5%8A%A8

(五)排队等待

匀速排队,让请求以均匀的速度通过,阀值类型必须设成QPS,否则无效。官方对排队等待的一个图解如下

 

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

 稍微修改一下 FlowLimitController ,增加日志的输出信息

package com.liuyangjava.controller;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class FlowLimitController {
    @Value("${server.port}")
    private String port;

    private Logger logger = LoggerFactory.getLogger(FlowLimitController.class);

    @GetMapping("/sentinel/service")
    public String getInfo() {
        return "sentinel service is running, server port: " + port;
    }

    @GetMapping("/sentinel/playInfo")
    public String playInfo() {
        logger.info(Thread.currentThread().getName()+"\t"+".../sentinel/playInfo");
        return "sentinel service is playInfo";
    }
}

最后通过JMeter进行压力测试,后端输出的接口,几乎就是2秒钟通过2个请求

 

 

posted @ 2021-11-05 17:01  子墨老师  阅读(133)  评论(0编辑  收藏  举报