Sentinel 限流使用案例

文章目录

    • 基本概念
    • 重要功能
    • 什么是Sentinel
      • Sentinel 具有以下特征
      • Sentinel 分为两个部分
    • 微服务集成Sentinel
      • 在pom.xml中加入下面依赖
      • 安装Sentinel控制台
      • 修改YML配置文件
      • 编写测试类
      • 流控规则
        • 流量控制(flow control)
        • 添加流量控制
      • 降级规则
        • 慢调用比例
        • 异常比例
        • 异常数
      • 热点规则
        • 热点规则高级选项
      • 授权规则
      • 系统规则
      • 自定义异常
  • 推荐文章
    • 觉得对您有帮助就留下个宝贵的吧!

基本概念

  • 资源

    • 资源就是Sentinel要保护的东西

      资源是 Sentinel 的关键概念。它可以是 Java 应用程序中的任何内容,可以是一个服务,也可以是 一个方法,甚至可以是一段代码。    
      
  • 规则

    • 规则就是用来定义如何进行保护资源的

      作用在资源之上, 定义以什么样的方式保护资源,主要包括流量控制规则、熔断降级规则以及系统 保护规则

重要功能

Sentinel 限流使用案例_第1张图片

Sentinel的主要功能就是容错,主要体现为下面这三个

  • 流量控制

    ​ 流量控制在网络传输中是一个常用的概念,它用于调整网络包的数据。任意时间到来的请求往往是 随机不可控的,而系统的处理能力是有限的。我们需要根据系统的处理能力对流量进行控制。 Sentinel 作为一个调配器,可以根据需要把随机的请求调整成合适的形状。

  • 熔断降级

    ​ 当检测到调用链路中某个资源出现不稳定的表现,例如请求响应时间长或异常比例升高的时候,则 对这个资源的调用进行限制,让请求快速失败,避免影响到其它的资源而导致级联故障。

    Sentinel 对这个问题采取了两种手段:

    • 通过并发线程数进行限制

      • Sentinel 通过限制资源并发线程的数量,来减少不稳定资源对其它资源的影响。当某个资源 出现不稳定的情况下,例如响应时间变长,对资源的直接影响就是会造成线程数的逐步堆 积。当线程数在特定资源上堆积到一定的数量之后,对该资源的新请求就会被拒绝。堆积的 线程完成任务后才开始继续接收请求。
    • 通过响应时间对资源进行降级

      • 除了对并发线程数进行控制以外, Sentinel 还可以通过响应时间来快速降级不稳定的资源。 当依赖的资源出现响应时间过长后,所有对该资源的访问都会被直接拒绝,直到过了指定的 时间窗口之后才重新恢复

      Sentinel 和 Hystrix 的区别

      ​ 两者的原则是一致的, 都是当一个资源出现问题时, 让其快速失败, 不要波及到其它服务 但是在限制的手段上, 确采取了完全不一样的方法: Hystrix 采用的是线程池隔离的方式, 优点是做到了资源之间的隔离, 缺点是增加了线程 切换的成本。 Sentinel 采用的是通过并发线程的数量和响应时间来对资源做限制。

  • 系统负载保护

    • Sentinel 同时提供系统维度的自适应保护能力。当系统负载较高的时候,如果还持续让 请求进入可能会导致系统崩溃,无法响应。在集群环境下,会把本应这台机器承载的流量转发到其 它的机器上去。如果这个时候其它的机器也处在一个边缘状态的时候, Sentinel 提供了对应的保 护机制,让系统的入口流量和系统的负载达到一个平衡,保证系统在能力范围之内处理最多的请求。

    总之一句话: 我们需要做的事情,就是在Sentinel的资源上配置各种各样的规则,来实现各种容错的功 能。

Sentinel 限流使用案例_第2张图片

什么是Sentinel

​ Sentinel (分布式系统的流量防卫兵) 是阿里开源的一套用于**服务容错**的综合性解决方案。它以流量 为切入点, 从流量控制熔断降级系统负载等多个维度来保护服务的稳定性。

Sentinel 限流使用案例_第3张图片

Sentinel 具有以下特征

  • 丰富的应用场景: Sentinel 承接了阿里巴巴近 10 年的双十一大促流量的核心场景, 例如秒杀(即 突发流量控制在系统容量可以承受的范围)、消息削峰填谷、集群流量控制、实时熔断下游不可用 应用等
  • 完备的实时监控: Sentinel 提供了实时的监控功能。通过控制台可以看到接入应用的单台机器秒 级数据, 甚至 500 台以下规模的集群的汇总运行情况
  • 广泛的开源生态: Sentinel 提供开箱即用的与其它开源框架/库的整合模块, 例如与 Spring Cloud、 Dubbo、 gRPC 的整合。只需要引入相应的依赖并进行简单的配置即可快速地接入 Sentinel。
  • 完善的 SPI 扩展点: Sentinel 提供简单易用、完善的 SPI 扩展接口。您可以通过实现扩展接口来快 速地定制逻辑。例如定制规则管理、适配动态数据源等。

Sentinel 分为两个部分

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

微服务集成Sentinel

为微服务集成Sentinel非常简单, 只需要加入Sentinel的依赖即可

在pom.xml中加入下面依赖

<dependency>
    <groupId>com.alibaba.cloudgroupId>
    <artifactId>spring-cloud-starter-alibaba-sentinelartifactId>
    <version>2.2.3version>
dependency>

安装Sentinel控制台

Sentinel 提供一个轻量级的控制台, 它提供机器发现、单机资源实时监控以及规则管理等功能。

  • 1 下载jar包,解压到文件夹 https://github.com/alibaba/Sentinel/releases
  • 2 启动控制台
#直接使用jar命令启动项目(控制台本身是一个SpringBoot项目)
java -Dserver.port=8000 -Dcsp.sentinel.dashboard.server=localhost:8000 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.8.0.jar

修改YML配置文件

spring:
  cloud:
    sentinel:
      transport:
        port: 9999 #跟控制台交流的端口,随意指定一个未使用的端口即可
        dashboard: localhost:8000 # 指定控制台服务的地址

编写测试类

@Api(tags = "Sentinel")
@RequestMapping(value = "/sentinel")
@RestController
public class DemoController1 {
     

    @ApiOperation(value = "测试方法1",httpMethod = "GET")
    @RequestMapping("/message1")
    public String message1() {
     
        return "message1";
    }

    @ApiOperation(value = "测试方法2",httpMethod = "GET")
    @RequestMapping("/message2")
    public String message2() {
     
        return "message2";
    }
}

流控规则

  • 正常接口测试是没有任何问题的

Sentinel 限流使用案例_第4张图片

登录我们的Sentinel管理平台,查看我们对应的服务,对需要的接口做流量控制

流量控制(flow control)

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

FlowSlot 会根据预设的规则,结合前面 NodeSelectorSlotClusterBuilderSlotStatisticSlot 统计出来的实时信息进行流量控制。

限流的直接表现是在执行 Entry nodeA = SphU.entry(resourceName) 的时候抛出 FlowException 异常。FlowExceptionBlockException 的子类,您可以捕捉 BlockException 来自定义被限流之后的处理逻辑。

同一个资源可以创建多条限流规则。FlowSlot 会对该资源的所有限流规则依次遍历,直到有规则触发限流或者所有规则遍历完毕。

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

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

Sentinel 限流使用案例_第5张图片

添加流量控制

  • 设置每秒请求数量
    Sentinel 限流使用案例_第6张图片

  • 资源名:唯一名称,默认是请求路径,可自定义

  • 针对来源:指定对哪个微服务进行限流,默认指default,意思是不区分来源,全部限制

  • 阈值类型/单机阈值

    • QPS(每秒请求数量) : 当调用该接口的QPS达到阈值的时候,进行限流
    • 线程数:当调用该接口的线程数达到阈值的时候,进行限流
  • 是否集群:暂不需要集群 接下来我们以QPS为例来研究限流规则的配置。

Sentinel 限流使用案例_第7张图片

  • 快速错误 (被Sentinel阻塞(流量限制)
    Sentinel 限流使用案例_第8张图片

降级规则

降级规则就是设置当满足什么条件的时候,对服务进行降级。Sentinel提供了三个衡量条件:

慢调用比例

  • 当资源的响应时间超过最大RT(以ms为单位,最大RT即最大响应时间)之后,资源进入准降级状态。如果接下来1s内持续进入1个请求(最小请求数),它们的RT都持续超过这个阈值,那么在接下来的熔断时长之内,就会对这个方法进行服务降级。

Sentinel 限流使用案例_第9张图片

异常比例

  • **异常比例:**当资源的每秒请求数大于等于最小请求数,并且异常总数占通过量的比例超过比例阈值时,资源进入降级状态。
@ApiOperation(value = "测试降级,异常", httpMethod = "GET")
    @RequestMapping("/message4")
    public String message4() {
     
        i++;
        if (i % 3 == 0) {
     
            throw new RuntimeException();
        }
        return "message3";
    }

Sentinel 限流使用案例_第10张图片

异常数

  • **异常数:**当资源近1分钟的异常数目超过阈值(异常数)之后会进行服务降级。注意由于统计时间窗口是分钟级别的,若熔断时长小于60s,则结束熔断状态后仍可能再次进入熔断状态。一般熔断时间要大于60s

Sentinel 限流使用案例_第11张图片

热点规则

热点参数流控规则是一种更细粒度的流控规则, 它允许将规则具体到参数上。

  • 热点规则简单使用
@ApiOperation(value = "测试热点规则", httpMethod = "GET")
@RequestMapping("/message5")
@SentinelResource("message5")//注意这里必须使用这个注解标识,热点规则不生效
public String message5(String name, Integer age) {
     
    return name + age;
}
  • 添加热点规则

Sentinel 限流使用案例_第12张图片

  • 参数索引:标识方法参数的下标,从0开始限制热点参数

  • 测试热点规则

    分别用两个参数访问,会发现只对第一个参数限流了,下标为0的参数已经被热点规则限制

Sentinel 限流使用案例_第13张图片

热点规则高级选项

参数例外项允许对一个参数的具体值进行流控
编辑刚才定义的规则,增加参数例外项,这样进行测试传递name=1 测试不会被限流

Sentinel 限流使用案例_第14张图片

授权规则

​ 很多时候,我们需要根据调用来源来判断该次请求是否允许放行,这时候可以使用 Sentinel 的来源访问
控制的功能。来源访问控制根据资源的请求来源(origin)限制资源是否通过:

  • 若配置白名单,则只有请求来源位于白名单内时才可通过;
  • 若配置黑名单,则请求来源位于黑名单时不通过,其余的请求通过。
  • Sentinel 限流使用案例_第15张图片

上面的资源名和授权类型不难理解,但是流控应用怎么填写呢?

​ 其实这个位置要填写的是来源标识,Sentinel提供了 RequestOriginParser 接口来处理来源。
只要Sentinel保护的接口资源被访问,Sentinel就会调用 RequestOriginParser 的实现类去解析
访问来源

  • 第1步: 自定义来源处理规则
@Component
public class RequestOriginParserDefinition implements RequestOriginParser {
     

    @Override
    public String parseOrigin(HttpServletRequest request) {
     
        String serviceName = request.getParameter("serviceName");
        return serviceName;
    }

}
  • 第2步: 授权规则配置
    这个配置的意思是只有serviceName=黑名单 不能访问(黑名单),其余的都可以访问

Sentinel 限流使用案例_第16张图片

  • 第2步: 测试授权

在这里插入图片描述

系统规则

​ 系统保护规则是从应用级别的入口流量进行控制,从单台机器的总体 Load、RT、入口 QPS 、CPU使用
率和线程数五个维度监控应用数据,让系统尽可能跑在最大吞吐量的同时保证系统整体的稳定性。系统
保护规则是应用整体维度的,而不是资源维度的,并且仅对入口流量 (进入应用的流量) 生效。

  • Load(仅对 Linux/Unix-like 机器生效):当系统 load1 超过阈值,且系统当前的并发线程数超过
    系统容量时才会触发系统保护。系统容量由系统的 maxQps * minRt 计算得出。设定参考值一般
    是 CPU cores * 2.5。
  • RT:当单台机器上所有入口流量的平均 RT 达到阈值即触发系统保护,单位是毫秒。
  • 线程数:当单台机器上所有入口流量的并发线程数达到阈值即触发系统保护。
  • 入口 QPS:当单台机器上所有入口流量的 QPS 达到阈值即触发系统保护。
  • CPU使用率:当单台机器上所有入口流量的 CPU使用率达到阈值即触发系统保护

自定义异常

import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.BlockExceptionHandler;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.authority.AuthorityException;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeException;
import com.alibaba.csp.sentinel.slots.block.flow.FlowException;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowException;
import com.alibaba.csp.sentinel.slots.system.SystemBlockException;
import com.alibaba.fastjson.JSON;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * sentinel 异常处理类
 */
@Component
public class ExceptionHandlerPage implements BlockExceptionHandler {
     

    //BlockException 异常接口,包含Sentinel的五个异常
    //@SentinelResource 用于定义资源,并提供可选的异常处理和 fallback 配置项。其主要参数如下:
    // FlowException 限流异常
    // DegradeException 降级异常
    // ParamFlowException 参数限流异常
    // AuthorityException 授权异常
    // SystemBlockException 系统负载异常
    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, BlockException e) throws Exception {
     
        response.setContentType("application/json;charset=utf-8");
        ResponseData data = null;
        if (e instanceof FlowException) {
     
            data = new ResponseData(-1, "接口被限流了...");
        } else if (e instanceof DegradeException) {
     
            data = new ResponseData(-2, "接口被降级了...");
        } else if (e instanceof ParamFlowException) {
     
            data = new ResponseData(-3, "参数限流异常...");
        } else if (e instanceof AuthorityException) {
     
            data = new ResponseData(-4, "授权异常...");
        } else if (e instanceof SystemBlockException) {
     
            data = new ResponseData(-5, "系统负载异常...");
        }
        response.getWriter().write(JSON.toJSONString(data));
    }
}


@Data
@AllArgsConstructor//全参构造
@NoArgsConstructor
//无参构造
class ResponseData {
     
    private int code;
    private String message;
}

推荐文章

Spring Cloud Alibaba 系列学习笔记
SpringCloud Alibaba Nacos
SpringCloud Alibaba Sentinel
@SentinelResource注解总结,异常、降级兜底
SpringCloud Alibaba Sentine 规则持久化
SpringCloud Alibaba RocketMQ
Seata1.4.2分布式事务整合nacos+SpringCloudAlibaba

觉得对您有帮助就留下个宝贵的吧!

你可能感兴趣的:(分布式,spring,cloud,alibaba,sentinel,限流,并发,安全)