1 sentinel应用场景之雪崩问题
- 雪崩问题
微服务调用链路中的某个服务故障,引起整个链路中所有微服务都不可用,这就是雪崩。
- 解决雪崩问题常见四种方式
- 超时处理:设定超时时间,请求超过一定时间没有响应就返回错误;
- 舱壁模式:限定每个业务使用的线程数量;
- 熔断降级:由断路器统计业务执行的异常比例,如果超出阈值则会熔断该业务,拦截访问该业务的一切请求;
- 流量控制:限制业务访问的QPS,避免服务因流量的突增而产生故障;
2 限流技术
2.1 常见的限流技术对比
对比项 | Sentinel | Hystrix | |
---|---|---|---|
隔离策略 | 信号量隔离(并发线程数限流)(模拟信号量) | 线程池隔离/信号量隔离 | |
熔断降级策略 | 基于响应时间、异常比率、异常数 | 基于异常比率 | 快速失败的本质功能 |
实时统计实现 | 滑动窗口(LeapArray) | 滑动窗口(基于 RxJava) | |
扩展性 | 多个扩展点 | 插件的形式 | |
限流 | 基于QPS,支持基于调用关系的限流 | 有限的支持(并发线程数或信号量大小) | |
流量整形 | 支持预热模式、匀速器模式、预热排队模式 | 不支持(排队) | |
系统自适应保护 | 支持(仅对linux生效) | 不支持 | |
配置持久化 | ZooKeeper, Apollo, Nacos | Git/svn/本地文件 | |
黑白名单 | 支持 | 不支持 |
2.2 限流算法
- 计数器算法
在指定周期内累加访问次数,当访问次数达到设定的阈值时,触发限流策略,当进入下一个时间周期时进行访问次数清零; - 滑动窗口算法
为了解决计数器算法带来的临界问题,滑动窗口算法是在固定窗口中分割出多个小时间窗口,分别在每个小时间窗口中记录访问次数,然后根据时间将窗口往前滑动并删除过期的小时间窗口,最终只需要统计滑动窗口范围内的所有小时间窗口总数;sentinel就采用滑动窗口算法来实现限流; - 令牌桶限流算法
系统以一个恒定速度向固定容量的令牌桶中放入令牌,如果有我客户端请求过来,则需要先从令牌桶中拿到令牌以获得访问资格; - 漏桶限流算法
该算法主要作用是控制数据注入网络的速度,平滑网络上的突发流量;
在漏桶算法内部维护一个容器,这个容器以恒定速度出水,不管上面水流速度多快,漏桶水滴的流出速度始终保持不变。(中间件就使用了漏桶限流的思想,不管生产者的请求量多大,消息的处理能力取决于消费者)
3 服务熔断于降级
3.1 基本概念
在高并发场景中,由于微服务架构中服务拆分粒度较细,请求链路较长,如某个服务因为网络延迟或请求超时等原因不可用时,会导致当前请求阻塞,很可能出现请求堆积从而导致出现雪崩效应;
服务熔断:是指当某个服务提供者无法正常为服务调用者提供服务时,如请求超时、服务异常等,为了防止整个系统出现雪崩效应,暂时将出现故障的接口隔离出来,断绝与外部接口的联系,当触发熔断之后,后续一段时间内该服务调用者的请求都会直接失败,直到目标服务恢复正常;
服务降级需要有一个参考指标,一般有几种常见方案:
- 平均响应时间
- 异常比例
- 异常数量
4 Sentinel基本使用
4.1 基本概念
sentinel是分布式服务架构的轻量级流量控制组件,主要以流量为切入点,从限流、流量整形、服务降级、系统负载保护等多个维度来保障微服务的稳定性;
sentinel组成:
核心库、控制台
3.1 控制启动sentinel控制台
- 下载sentinel项目jar
https://github.com/alibaba/Sentinel/releases - 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
- 基本步骤
- 定义资源
- 定义限流规则
- 检验规则是否生效
- 创建父容器pom.xml
<?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>
- 创建自定义模块,加入sentinel依赖
<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>
- 添加sentinel服务配置 application.yml
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控制台页面
Sentinel的控制台其实就是一个SpringBoot编写的程序。我们需要将我们的微服务程序注册到控制台上,
即在微服务中指定控制台的地址, 并且还要开启一个跟控制台传递数据的端口, 控制台也可以通过此端口
调用微服务中的监控程序获取微服务的各种信息
3.4 实现接口限流
image.png4 sentinel功能
4.1 基本概念
- 资源
资源就是sentinel要保护的东西(可以是一个服务、一个方法或一段代码) - 规则
规则就是用来定义如何进行保护资源(流量控制规则、熔断降级规则以及系统保护规则)
4.2 容错的三个方面
- 流量控制
- 熔断降级(通过限制并发线程数和通过响应时间对资源进行降级)
- 系统负载保护
5 sentinel规则
5.1 流控规则
流量控制,其原理是监控应用流量的QPS(每秒查询率) 或并发线程数等指标,当达到指定的阈值时对流
量进行控制,以避免被瞬时的流量高峰冲垮,从而保障应用的高可用性;
image.png
资源名:唯一名称,默认是请求路径,可自定义
针对来源:指定对哪个微服务进行限流,默认指default,意思是不区分来源,全部限制
阈值类型单机阈值:QPS(每秒请求数量): 当调用该接口的QPS达到阈值的时候,进行限流
线程数:当调用该接口的线程数达到阈值的时候,进行限流
是否集群:暂不需要集群
- sentinel共有三种流控模式,分别是:
直接(默认):接口达到限流条件时,开启限流
关联:当关联的资源达到限流条件时,开启限流 [适合做应用让步]
链路:当从某个接口过来的资源达到限流条件时,开启限流
网友评论