Sentinel流量控制 及 热点规则

1.简介

1.1Sentinel 是什么?

随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。

1.2Sentinel的主要特性

image-20200816211615511

1.3解决服务中的哪些问题

image-20200816211735946

1.4Sentinel组件

image-20200816211849328

2.安装Sentinel控制台

运行环境:java8+

官方Github下载

在这里我使用的是1.7.0 版本 ,切换版本点击 Tags

image-20200816212434360

下载完毕之后,在当前目录进入cmd命令窗口,输入命令java -jar sentinel-dashboard-1.7.0.jar

注意:sentinel控制启动使用的8080端口,所以8080端口不能被占用

image-20200816212911052

如此,我们访问 http://localhost:8080 即可访问到控制台界面

image-20200816213011124

默认的账号密码都是sentinel,登录成功我们的控制台就启动完成了

3.服务搭建

在这里我们搭建一个服务来演示sentinel的流量控制

3.1搭建项目基础

pom

在这里springcloud-alibaba使用的是2.1.0.RELEASE版本,spring-boot使用的是2.2.2.RELEASE版本

  <dependencies>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>
        <!-- SpringBoot整合Web组件+actuator -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <!--日常通用jar包配置-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

yml

注意:在使用sentinel时,要暴露端口

server:
  port: 8401

spring:
  application:
    name: cloudalibaba-sentinel-service
  cloud:
    sentinel:
      transport:
        dashboard: localhost:8080 #配置Sentinel dashboard地址
        port: 8719 #指定应用与Sentinel控制台交互的端口,应用本地会起一个该端口占用的HttpServer,如果该端口被占用,该端口号自动+1

management:
  endpoints:
    web:
      exposure:
        include: '*'  ##暴露端口

主启动类

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * @author Xkuna
 * @date 2020/8/16 20:15.
 */
@SpringBootApplication
public class MainApp8401 {
    public static void main(String[] args) {
        SpringApplication.run(MainApp8401.class, args) ;
    }
}

3.2创建流控 controller

很简单,在这里我们只是创建了连个接口

import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author Xkuna
 * @date 2020/8/16 20:16.
 */
@RestController
@Slf4j
public class FlowLimitController {

    @GetMapping("/testA")
    public String testA() {
        return "----testA" ;
    }

    @GetMapping("/testB")
    public String testB() {
        return "----testB" ;
    }
}

3.3启动

启动该服务,访问 http://localhost:8080 登录成功后,会发现 列表中并不存在服务,这是为什么呢?

​ 原来,sentinel采用了懒加载机制,所以我们访问一下 http://localhost:8401/testA ,刷新控制台就会看到服务列表中存在我们的服务了,

image-20200816215201261

簇点链路中没有发现我们的testB接口,我们访问下http://localhost:8401/testB 刷新控制台 就可以看到了,

image-20200816215346695

4.流量控制规则

4.1 QPS 直接 快速失败 规则

image-20200816215747271

image-20200816215812028

先解释下什么是QPS

每秒查询率(QPS,Queries-per-second)是对一个特定的查询服务器在规定时间内所处理流量多少的衡量标准。

也就是每秒的请求数。

所以我们在这里设置的QPS为1,也就是每秒的请求数超过1会直接报错。

image-20200816220115277

4.2 线程数 直接 规则

先删除上面的流控规则

注意:流控规则中,QPS有流控效果,而线程数没有

image-20200816220340815

在这里我们设置的线程数为1,我们快速刷新 http://localhost:8401/testA ,发现不会报错。

那么线程数为1代表着什么呢?

​ 这里的线程数为1,代表着 后台有一个线程处理该 资源名 的请求, 当我们快速点第二次刷新时,线程已经处理完了上一次请求,所以不会报错,而会接着处理我们的请求

在这里我们可以修改下controller,让testA接口暂停 0.8秒

image-20200816220920623

注意!!!

​ 我们修改完controller重启服务,因为没有配置sentinel持久化规则(在该博文不介绍),所以sentinel中我们在上面设置的 线程直接规则会丢失,服务重启完刷新控制台,重新配置即可

我们用浏览器 快速多次 访问 http://localhost:8401/testA,

image-20200816221831903

此时证明,我们的规则配置生效了

4.3 QPS 关联 快速失败 规则

在配置该规则之前 我们把修改的controller 修改回来

image-20200816222150740

然后刷新sentinel控制台,创建我们的新的流控规则— QPS 关联 快速失败 规则

image-20200816222333557

这样配置的含义:

​ 当与A关联的资源B达到阈值后,就限流自己,简而言之:“B惹事,A挂了

此时,为了方便测试,我们用postman 连续访问 testB (连续访问200次, 每次0.3s),我们在用浏览器访问testA

image-20200816222635042

image-20200816222650280

image-20200816222751863

此时,我们可以看出我们配置的规则生效了,

4.4 QPS 直接 预热 规则

image-20200816222948112

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

在这里我们的配置的含义是:大量请求开始在预热时长 5 s 内,QPS阈值慢慢的从3(10 / 3)长到 10

请求 http://localhost:8401/testA 快速刷新,发现前5s 大量请求中会出现报错,5s后几乎没有报错(手动刷新请求很难做到QPS > 10)

如此,我们的配置生效了

4.5QPS 直接 排队等待 规则

我们首先将之前的规则全部删除

然后配置新的规则

image-20200816223728234

这里的规则的含义是:

QPS 阈值为1,如果一秒内QPS > 1,那么这些请求不会直接失败,而是在 设置的超时时间内排队,超时时间内还没有请求资源,那么该请求才会失败。

以上是常用的几种Sentinel流量控制规则 😄

5.自定义返回信息

我们发现 服务在违背 流量控制规则时,返回的信息为sentinel默认返回的,实际上是可以自定义的

在这里修改controller

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;


/**
 * @author Xkuna
 * @date 2020/8/16 20:16.
 */
@RestController
@Slf4j
public class FlowLimitController {

    @GetMapping("/testA")
    //value 可以随便起 保证唯一即可,一般是url路径取消斜线
    @SentinelResource(value = "testA", blockHandler = "testAHandler")
    public String testA() {
        return "----testA" ;
    }
    // 自定义blockHandler 一定要传入 BlockException 否则不起效
    public String testAHandler(BlockException blockException){
        return  "testA blockException-----" ;
    }

    @GetMapping("/testB")
    public String testB() {
        return "----testB" ;
    }
}

此时先访问下 http://localhost:8401/testA

然后登录控制台 发现多了一个资源路径 testA

image-20200817171100047

所以 要想我们自定义的BlockHandler生效 ,在配置流量规则时的资源名就得是 代码中 @SentinelResourcevalue

image-20200817171423053

多次连续访问 http://localhost:8401/testA

image-20200817171451583

所以我们自定义的 @SentinelResourceblockHandler生效了


关于@SentinelResource注解

  • @SentinelResource 写在业务类方法上

  • value是我们自定义的资源名

  • blockHandler是违背sentinel的规则(流控,熔断降级,热点规则等等)时的处理方法

    除了这些还有我们下面要讲的

  • blockHandlerClass:每个方法都配一个 blockHandler会导致代码臃肿,耦合度高,所以我们可以配置一个类单独配置blockHandler,使用时用blockHandlerClass指向类,blockHandler指向方法即可

还有处理java程序运行时出现错误的 fallbackHandlerClass以及 fallbackHander,在这里就不赘述了


6.配置HandlerClass

import com.alibaba.csp.sentinel.slots.block.BlockException;

/**
 * @author Xkuna
 * @date 2020/8/17 17:29.
 */
public class MyHandler {
    public static String blockHandlerInfo(BlockException blockException){
        return "---自定义blockHandlerInfo" ;
    }
}

修改controller

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import top.xkuna.springcloud.myHandler.MyHandler;


/**
 * @author Xkuna
 * @date 2020/8/16 20:16.
 */
@RestController
@Slf4j
public class FlowLimitController {

    @GetMapping("/testA")
    @SentinelResource(value = "testA", blockHandlerClass = MyHandler.class, blockHandler = "blockHandlerInfo")
    public String testA() {
        return "----testA" ;
    }
    // 自定义blockHandler 一定要传入 BlockException 否则不起效
//    public String testAHandler(BlockException blockException){
//        return  "testA blockException-----" ;
//    }

    @GetMapping("/testB")
    public String testB() {
        return "----testB" ;
    }
}

此时,重启8401服务,访问 一次 http://localhost:8401/testA

进入控制台 看到testA资源名称入驻

image-20200817173621837

添加流控规则

image-20200817173644753

多次刷新访问 http://localhost:8401/testA

image-20200817173707206

此时,我们配置的blockHandlerClass 成功😄

7.热点规则

在sentinel中特别的划分出了热点规则,在这里我们配置下

image-20200817192622440

修改controller(添加/hot接口)

注意:热点规则配置的blockHandler需要按照原方法 传参,参数也不可缺少BlockException, 所以在这里我们就不使用blockHandlerClass

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import top.xkuna.springcloud.myHandler.MyHandler;


/**
 * @author Xkuna
 * @date 2020/8/16 20:16.
 */
@RestController
@Slf4j
public class FlowLimitController {

    @GetMapping("/testA")
    @SentinelResource(value = "testA", blockHandlerClass = MyHandler.class, blockHandler = "blockHandlerInfo")
    public String testA() {
        return "----testA" ;
    }
    // 自定义blockHandler 一定要传入 BlockException 否则不起效
//    public String testAHandler(BlockException blockException){
//        return  "testA blockException-----" ;
//    }

    @GetMapping("/testB")
    public String testB() {
        return "----testB" ;
    }
	
    @GetMapping("/hot")
    @SentinelResource(value = "hot", blockHandler = "blockHandlerHot")
    public String hot(@RequestParam(value = "type", required = false) String type,
                      @RequestParam(value = "name", required = false) String name){
        return "hot controller" ;
    }
	//注意参数要跟原方法一直 ,但要加上 BlockException参数
    public String blockHandlerHot(String type, String name, BlockException blockException){
        return "hot blockHandler" ;
    }
}

重启服务,访问 http://localhost:8401/hot 刷新控制台

image-20200817193245840

找到左侧菜单栏的 热点规则

7.1 普通配置

image-20200817193347963

发现只支持QPS模式

  • 参数索引:是 我们controller hot 接口的参数下标,在这里指的是 参数 type
  • 单机阈值:在这里是1,所以一秒钟允许通过1个请求
  • 窗口时长:是在访问该资源QPS超过阈值,触发该规则的有效期,超过后重新统计

在这里我们的接口两个参数都为非必须传参,又因为热点规则的索引为0(限制参数为type),所以我们此时请求的url

只要不含有 type参数,该规则与请求无关

访问 http://localhost:8401/hot 和 http://localhost:8401/hot?name=xxx 多次连续刷新请求,都会发现没有触发我们的热点规则

image-20200817194620300

此时我们访问 http://localhost:8401/hot?type=xxx 或者 http://localhost:8401/hot?type=xxx&name=xxxx

只要携带了参数type,当我们多次快速刷新请求时,就会触发热点规则,并返回我们自定义的blockHandler

image-20200817194605300

热点规则的普通配置生效!

7.2高级配置

image-20200817194827045

此时,我们配置了参数例外项

不论普通配置还是高级配置,一个热点规则都是针对一个参数,只有携带此参数的url才生效

解释下这样配置的含义:

  • url含有参数type该规则才生效,不含有参数type的url直接忽略该规则
  • 参数type的值为ok时,阈值为1,参数type的值为其他时,阈值为5
  • 窗口时长为5 s

测试ok,sentinel流控规则热点规则就是这些了 😃

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值