微服务 springcloudAlibab-day03之Sentinel 流控规则

Sentinel介绍

什么是Sentinel

  1. sentinel是以"流量"为切入点,在流量控制、短路 ,负载保护等多个领域,保证服务可靠性
  2. 特点:
    2.1 +丰富的应用场景:Sentinel 承接了阿里巴巴近 10 年的双十一大促流量的核心场景,例如秒杀(即突发流量控制在系统容量可以承受的范围)、消息削峰填谷、集群流量控制、实时熔断下游不可用应用等。
    2.2 完备的实时监控:Sentinel 同时提供实时的监控功能。您可以在控制台中看到接入应用的单台机器秒级数据,甚至 500 台以下规模的集群的汇总运行情况。
    2.3 广泛的开源生态:Sentinel 提供开箱即用的与其它开源框架/库的整合模块,例如与 Spring Cloud、Apache Dubbo、gRPC、Quarkus 的整合。您只需要引入相应的依赖并进行简单的配置即可快速地接入 Sentinel。同时 Sentinel 提供 Java/Go/C++ 等多语言的原生实现。
    2.4 . 完善的 SPI 扩展机制:Sentinel 提供简单易用、完善的 SPI 扩展接口。您可以通过实现扩展接口来快速地定制逻辑。例如定制规则管理、适配动态数据源等。
    3. 官网地址:https://github.com/alibaba/Sentinel/wiki/%E4%BB%8B%E7%BB%8D

    Sentinel下载和完整

    下载地址:https://github.com/alibaba/Sentinel/releases
    在这里插入图片描述
    官方提供的手册:https://spring-cloud-alibaba-group.github.io/github-pages/hoxton/en-us/index.html#_spring_cloud_alibaba_sentinel

Sentinel 分为两个部分

  • 核心库(Java客户端)不依赖任何框架/库,只需要Java运行时环境,同时对Dubbo/SpringCloud 等框架也有较好的支持。
  • 控制台(Dashboard)基于 SpringBoot开发,打包后可以直接运行,不需要额外的Tomcat等应用容器。

启动步骤

  • 前提:jdk1.8环境和8080端口不能被占用

  • 启动命令:java -jar sentinel-dashboard-1.8.2.jar

  • 访问地址:localhost:8080

  • 输入默认账号密码:sentinel/sentinel
    在这里插入图片描述

Sentinel初始化监控

Sentinel 初始化工程演示

我们现在通过一个案例来让大家了解Sentinel的初始化演示,现在我们需要做几件事:

  1. 启动Nacos8848成功
  2. 创建新的Module:cloudalibaba-sentinel-service8401
  3. 启动Sentinel8080
  4. 启动微服务8401
  5. 启动8401微服务后查看Sentinel控制台

搭建Sentinel项目

  1. Sentinel的官方文档网址:https://sentinelguard.io/zh-cn/docs/quick-start.html
  2. 创建项目cloudalibaba-sentinel-service8401
  3. 导入依赖:
<!-- Nacos客户端依赖 -->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- sentinel依赖 -->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
  1. 配置yaml文件,目的是让当前8401注册进Nacos,然后被Sentinel8080进行监控
server:
  port: 8401
spring:
  application:
    name: cloud-sentinel-service
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848 #nacos注册中心
    sentinel:
      transport:
#        配置sentinel dashboard地址
        dashboard: 127.0.0.1:8080
#        默认8719端口,键入被占用会自动8719+1,直到未被占用端口
        port: 8719
management:
  endpoint:
    web:
      exposure:
        include: '*'
  1. 编写FlowLimitController
package com.gek.cloudalibabasentinelservice8401.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

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

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

测试

  1. 当以上的这些配置配置好以后,我们就可以进行测试了,那我们的测试方式就是,首先保证Nacos和Sentinel都是启动状态,然后再来启动项目,按照我们的理解这个时候,就应该在Sentinel的dashboard上能体现出它监控的服务,但是此时并没有,原因是因为Sentinel本身采用的是懒加载机制,所以我们需要首先访问服务对应的接口,Sentinel才能工作。
http://localhost:8401/testA
http://localhost:8401/testB
  1. 访问之后我们来查看Sentinel的dashboard
    在这里插入图片描述

Sentinel流控规则

在这里插入图片描述

名词解释

  • 资源名:唯一名称,默认请求路径
  • 针对来源:Sentinel可以针对调用者进行限流,填写微服务名,默认default(不区分来源)
  • 阈值类型/单机阈值:
  • QPS(每秒钟的请求数量):当调用该API的QPS达到阈值的时候,进行限流
  • 线程数:当调用该API的线程数量达到阈值的时候,进行限流
  • 是否集群:当前不需要集群
  • 流控模式:
    • 直接:API达到限流条件时,直接限流
    • 关联:当关联的资源达到阈值时,就限流自己
    • 链路:只记录指定链路上的流量(指定资源从入口资源进来的流量,如果达到阈值,就进行限流)(API级别的针对来源)
  • 流控效果:
    • 快速失败:直接失败,抛异常
    • Wam Up:根据codeFactor(冷加载因子,默认3)的值,从阈值/codeFacotor,经过预热时长,才达到设置的QPS阈值
    • 排队等待:匀速排队,让请求以匀速的速度通过,阈值类型必须设置为QPS,否则无效

    具体操作

新增流控

QPS直接失败案例

  1. 添加有两种方式,可以直接在流控规则选项中添加,也可以在簇点链路中添加,一般会采取第二种方式

在这里插入图片描述

  1. 现在我们给/testA添加流控
    在这里插入图片描述

  2. 这里的意思就是我们现在单机阈值设定为1,代表的是当前这个接口只能被1秒访问一次,超过这个阈值,就会被Sentinel阻塞,现在默认为直接失败,也就是会在前台有一个体现

在这里插入图片描述

线程数直接失败案例

  1. 刚才我们可以的设置是通过QPS(每秒钟请求的数量)来设置的限流规则,但是我们这里其实还有一个线程数,是什么意思那?
  2. 添加线程流控
    在这里插入图片描述
  3. 那我们要演示这种效果,我们就需要让一个线程再进来办理的时候需要0.8秒,但是这个时候后面的线程也在疯狂的访问,所以后面的线程就会不会生效。
package com.gek.cloudalibabasentinelservice8401.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.TimeUnit;

@RestController
public class FlowLimitController {
    @GetMapping("/testA")
    public String testA(){
        try {
            TimeUnit.MILLISECONDS.sleep(800);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "------testA";
    }

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

  1. 这个时候我们重启项目,然后重新通过访问testA接口,通过两个网页(线程)来快速访问,这个时候我们来看效果,这里要注意,要重新添加流控规则。
    在这里插入图片描述

流控规则-关联

关联

​ 官方解释:当关联的资源达到阈值时,就限流自己。

通俗解释来说,比如那我们的程序,现在有testA接口和testB接口,当A关联的资源B达到阈值后,就限流自己,也就是B到达阈值,限流A本身。就好像我家孩子在外面打架,我来处理一样。换到程序里面来说比如一个电商系统中,支付系统达到阈值,就限流下订单系统。

在这里插入图片描述

具体演示

  1. 给 testA添加流控规则
    在这里插入图片描述
  2. ​ 为了演示效果,所以这里我们需要借助一个工具Postman,来模仿并发密集访问/testB,先来测试访问testB接口
    在这里插入图片描述
    ​ 这个时候我们需要多次密集访问TestB接口,所以我们需要添加配置,具体操作如下:
    在这里插入图片描述
    把数值修改为:
  • Iterations:为20
  • Delay:300
    意思就是20个线程每间隔0.3秒访问一次,然后跑起来
    在这里插入图片描述
    这时候我们看testA的效果
    在这里插入图片描述

流控规则-链路

链路

​ 链路流控模式指的是,当从某个接口过来的资源达到限流条件时,开启限流,它的功能有点类似于针对来源配置项,区别在于:针对来源是针对上级微服务,而链路流控是针对上级接口,也就是说它的粒度更细。

​ 比如在一个微服务中,两个接口都调用了同一个Service中的方法,并且该方法用SentinelResource(用于定义资源)注解标注了,然后对该注解标注的资源(方法)进行配置,则可以选择链路模式。

具体演示

  1. 首先编写一个Service
package com.gek.cloudalibabasentinelservice8401.service;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import org.springframework.stereotype.Service;

@Service
public class TestService {
    //定义限流资源
    @SentinelResource("common")
    public String common(){
        return "common";
    }
}

  1. 然后更改接口调用这个Service方法
package com.gek.cloudalibabasentinelservice8401.controller;

import com.gek.cloudalibabasentinelservice8401.service.TestService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.TimeUnit;

@RestController
public class FlowLimitController {
    @Autowired
    private TestService testService;

    @GetMapping("/testA")
    public String testA(){
        return testService.common();
    }

    @GetMapping("/testB")
    public String testB(){
        return testService.common();
    }
}

  1. 接下来配置流控规则:

这里要注意不要对/testA或者/testB进行限流规则的配置,要给用SentinelResource注解标注的资源进行配置限流规则,这里的意思为当我们用入口资源访问被SentinelResource注解标注的资源方法时,当超过阈值就会被限流。

配置链路流控:web-context-unify: false

server:
  port: 8401
spring:
  application:
    name: cloud-sentinel-service
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848 #nacos注册中心
    sentinel:
      transport:
#        配置sentinel dashboard地址
        dashboard: 127.0.0.1:8080
#        默认8719端口,键入被占用会自动8719+1,直到未被占用端口
        port: 8719
        # 默认将调用链路收敛,需要打开才可以进行链路流控
      web-context-unify: false
management:
  endpoint:
    web:
      exposure:
        include: '*'

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

流控规则-预热

预热

官网手册地址:https://sentinelguard.io/zh-cn/docs/flow-control.html

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

​ 预热公式:阈值/coldFactor(默认值为3),经过预热时间后才会达到阈值。

​ 冷启动的过程系统允许通过的QPS曲线如下图:
在这里插入图片描述
简单理解:
在这里插入图片描述
使用场景:一般秒杀系统中会有这样的流控设置,为了防止秒杀瞬间造成系统崩溃。
案例:
在这里插入图片描述
测试,我们用最简单的方法进行测试,直接在浏览器上手动刷新,然后我们来看Sentinel的实时监控
在这里插入图片描述

蓝线代表拒绝的,绿线代表允许的,请求一开始会拒绝报错,过5秒后,就能正常访问

Sentinel流控效果-排队等待

  • 流控效果:
    • 排队等待(匀速器):匀速排队,让请求以匀速的速度通过,阈值类型必须设置为QPS,否则无效

    排队等待

​ 官方文档:https://sentinelguard.io/zh-cn/docs/flow-control.html
概念:匀速排队方式会严格控制请求通过的间隔时间,也即是让请求以均匀的速度通过,对应的是漏桶算法。
​ 这种方式主要用于处理间隔性突发的流量,例如消息队列。想象一下这样的场景,在某一秒有大量的请求到来,而接下来的几秒则处于空闲状态,我们希望系统能够在接下来的空闲期间逐渐处理这些请求,而不是在第一秒直接拒绝多余的请求(削峰填谷)。
在这里插入图片描述
匀速器
​ 它的中心思想是,以固定的间隔时间让请求通过。当请求到来的时候,如果当前请求距离上个通过的请求通过的时间间隔不小于预设值,则让当前请求通过。否则,计算当前请求的预期通过时间,如果该请求的预期通过时间小于规则预设的 timeout 时间,则该请求会等待直到预设时间到来通过(排队等待处理);若预期的通过时间超出最大排队时长,则直接拒接这个请求。

在这里插入图片描述
Sentinel 匀速排队等待策略是漏桶算法结合虚拟队列等待机制实现的。

​ 注意:匀速排队模式暂时不支持 QPS > 1000 的场景。

演示:

 流控规则:

在这里插入图片描述

为了看到效果,我们在代码中进行打印,更改8401微服务中的FlowLimitController

package com.gek.cloudalibabasentinelservice8401.controller;

import com.gek.cloudalibabasentinelservice8401.service.TestService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;


@RestController
@Slf4j
public class FlowLimitController {
    @Autowired
    private TestService testService;

    @GetMapping("/testA")
    public String testA(){
        log.info(Thread.currentThread().getName()+"testA");
        return testService.common();
    }

    @GetMapping("/testB")
    public String testB(){
        return testService.common();
    }
}

最后我们可以通过Postman来进行测试,发送请求时没有延迟,同时发送10条请求,然后我们会发现就是排队效果1秒执行一个请求,同时我们在Idea中也可以看到打桩效果
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值