02-sentinel限流与熔断

2022-12-19  本文已影响0人  wshsdm

1 sentinel应用场景之雪崩问题

微服务调用链路中的某个服务故障,引起整个链路中所有微服务都不可用,这就是雪崩。

  1. 超时处理:设定超时时间,请求超过一定时间没有响应就返回错误;
  2. 舱壁模式:限定每个业务使用的线程数量;
  3. 熔断降级:由断路器统计业务执行的异常比例,如果超出阈值则会熔断该业务,拦截访问该业务的一切请求;
  4. 流量控制:限制业务访问的QPS,避免服务因流量的突增而产生故障;

2 限流技术

2.1 常见的限流技术对比

对比项 Sentinel Hystrix
隔离策略 信号量隔离(并发线程数限流)(模拟信号量) 线程池隔离/信号量隔离
熔断降级策略 基于响应时间、异常比率、异常数 基于异常比率 快速失败的本质功能
实时统计实现 滑动窗口(LeapArray) 滑动窗口(基于 RxJava)
扩展性 多个扩展点 插件的形式
限流 基于QPS,支持基于调用关系的限流 有限的支持(并发线程数或信号量大小)
流量整形 支持预热模式、匀速器模式、预热排队模式 不支持(排队)
系统自适应保护 支持(仅对linux生效) 不支持
配置持久化 ZooKeeper, Apollo, Nacos Git/svn/本地文件
黑白名单 支持 不支持

2.2 限流算法

  1. 计数器算法
    在指定周期内累加访问次数,当访问次数达到设定的阈值时,触发限流策略,当进入下一个时间周期时进行访问次数清零;
  2. 滑动窗口算法
    为了解决计数器算法带来的临界问题,滑动窗口算法是在固定窗口中分割出多个小时间窗口,分别在每个小时间窗口中记录访问次数,然后根据时间将窗口往前滑动并删除过期的小时间窗口,最终只需要统计滑动窗口范围内的所有小时间窗口总数;sentinel就采用滑动窗口算法来实现限流;
  3. 令牌桶限流算法
    系统以一个恒定速度向固定容量的令牌桶中放入令牌,如果有我客户端请求过来,则需要先从令牌桶中拿到令牌以获得访问资格;
  4. 漏桶限流算法
    该算法主要作用是控制数据注入网络的速度,平滑网络上的突发流量;
    在漏桶算法内部维护一个容器,这个容器以恒定速度出水,不管上面水流速度多快,漏桶水滴的流出速度始终保持不变。(中间件就使用了漏桶限流的思想,不管生产者的请求量多大,消息的处理能力取决于消费者)

3 服务熔断于降级

3.1 基本概念

在高并发场景中,由于微服务架构中服务拆分粒度较细,请求链路较长,如某个服务因为网络延迟或请求超时等原因不可用时,会导致当前请求阻塞,很可能出现请求堆积从而导致出现雪崩效应;
服务熔断:是指当某个服务提供者无法正常为服务调用者提供服务时,如请求超时、服务异常等,为了防止整个系统出现雪崩效应,暂时将出现故障的接口隔离出来,断绝与外部接口的联系,当触发熔断之后,后续一段时间内该服务调用者的请求都会直接失败,直到目标服务恢复正常;
服务降级需要有一个参考指标,一般有几种常见方案:

  1. 平均响应时间
  2. 异常比例
  3. 异常数量

4 Sentinel基本使用

4.1 基本概念

sentinel是分布式服务架构的轻量级流量控制组件,主要以流量为切入点,从限流、流量整形、服务降级、系统负载保护等多个维度来保障微服务的稳定性;
sentinel组成:
核心库、控制台

3.1 控制启动sentinel控制台

配置项 默认值 说明
server.port 8080 默认端口
sentinel.dashboard.auth.username sentinel 用户名
sentinel.dashboard.auth.password sentinel 密码
java -Dserver.port=8000 -Dcsp.entinel.dashboard.server=localhost:8000 -Dproject.name=sentinel-dashboard  -jar sentinel-dashboard-1.8.6.jar 

3.3 微服务中整合sentinel

  1. 定义资源
  2. 定义限流规则
  3. 检验规则是否生效
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.pingsp</groupId>
    <artifactId>pingsp-parent</artifactId>
    <version>1.0-SNAPSHOT</version>
    <modules>
        <module>pingsp-security</module>
    </modules>
    <packaging>pom</packaging>
    <!--统一版本-->
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <!-- spring boot -->
        <spring-boot.version>2.4.2</spring-boot.version>
        <!-- spring cloud -->
        <spring-cloud.version>2020.0.1</spring-cloud.version>
        <spring-cloud-alibaba.version>2021.1</spring-cloud-alibaba.version>
        <!-- db && orm -->
        <mysql.version>8.0.19</mysql.version>
        <druid.version>1.2.4</druid.version>
        <mybatis-plus.version>3.4.3</mybatis-plus.version>
        <!-- tools -->
        <lombok.version>1.18.24</lombok.version>
        <hutool.version>5.8.5</hutool.version>
        <!--自定义依赖库版本-->
        <project.version>1.0-SNAPSHOT</project.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>${lombok.version}</version>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>${hutool.version}</version>
        </dependency>
    </dependencies>
    <dependencyManagement>
        <dependencies>
            <!--Spring Cloud 相关依赖-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!--Spring Cloud & Alibaba 相关依赖-->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${spring-cloud-alibaba.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!-- SpringBoot 依赖配置 -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!--持久层依赖配置-->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>${mysql.version}</version>
            </dependency>
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid-spring-boot-starter</artifactId>
                <version>${druid.version}</version>
            </dependency>
            <dependency>
                <groupId>com.baomidou</groupId>
                <artifactId>mybatis-plus-boot-starter</artifactId>
                <version>${mybatis-plus.version}</version>
            </dependency>
            <!--流量控制-->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
                <version>${spring-cloud-alibaba.version}</version>
            </dependency>
            <!--自定义通用模块-->
        </dependencies>
    </dependencyManagement>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                    <encoding>${project.build.sourceEncoding}</encoding>
                </configuration>
            </plugin>
        </plugins>
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.xml</include>
                </includes>
                <filtering>true</filtering>
            </resource>
            <resource>
                <directory>src/main/resources</directory>
                <filtering>true</filtering>
            </resource>
        </resources>
    </build>
</project>
<dependencies>
        <!-- 配置读取 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
        </dependency>
        <!-- Spring Cloud & Alibaba -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bootstrap</artifactId>
        </dependency>
        <!-- 注册中心 -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-loadbalancer</artifactId>
        </dependency>
        <!-- 配置中心 -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>
    </dependencies>
    <build>
        <finalName>${project.artifactId}</finalName>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
server:
  port: 8001
spring:
  application:
    # 应用程序名称
    name: pingsp-security
  cloud:
    nacos:
      discovery:
        # 服务发现
        server-addr: localhost:8848
      config:
        # 配置服务器
        server-addr: localhost:8848
        shared-configs:
          - dataId: ds.yaml
            refresh: true
    sentinel:
      transport:
        port: 9999 #跟控制台交流的端口,随意指定一个未使用的端口即可
        dashboard: localhost:8000 #指定控制台服务的地址

Sentinel的控制台其实就是一个SpringBoot编写的程序。我们需要将我们的微服务程序注册到控制台上,
即在微服务中指定控制台的地址, 并且还要开启一个跟控制台传递数据的端口, 控制台也可以通过此端口
调用微服务中的监控程序获取微服务的各种信息

3.4 实现接口限流

image.png

4 sentinel功能

4.1 基本概念

4.2 容错的三个方面

  1. 流量控制
  2. 熔断降级(通过限制并发线程数和通过响应时间对资源进行降级)
  3. 系统负载保护

5 sentinel规则

5.1 流控规则

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


image.png

资源名:唯一名称,默认是请求路径,可自定义
针对来源:指定对哪个微服务进行限流,默认指default,意思是不区分来源,全部限制
阈值类型单机阈值:QPS(每秒请求数量): 当调用该接口的QPS达到阈值的时候,进行限流
线程数:当调用该接口的线程数达到阈值的时候,进行限流
是否集群:暂不需要集群

上一篇下一篇

猜你喜欢

热点阅读