SpringCloud实战之路 | 应用篇(十)Spring Cloud Alibaba服务哨兵Sentinel
文章内容输出来源:拉勾教育Java高薪训练营;
Sentinel介绍
Sentinel是⼀个⾯向云原⽣微服务的流量控制、熔断降级组件,可以用来替代Hystrix解决服务雪崩、服务降级、服务熔断、服务限流等问题。
对比Hystrix来说,Sentinel提供了独⽴可部署Dashboard控制台组件,通过在控制台进行配置即可完成对服务的限流、熔断、降级等控制,减少了代码部分的开发
下载地址:https://github.com/alibaba/Sentinel/releases
Sentinel部署
默认端口:8080,有冲突记得修改,这里改为了8090
启动命令:
java -jar sentinel-dashboard-1.7.1.jar --server.port=8090 &
默认⽤户名/密码:sentinel/sentinel
访问:http://localhost:8090/#/dashboard/home
服务整合Sentinel
引入maven依赖
<!--sentinel 核⼼环境 依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
修改yml配置文件
server:
port: 8080
spring:
application:
name: cloud-service-user
main:
allow-bean-definition-overriding: true
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
config:
server-addr: 127.0.0.1:8848
file-extension: yaml
sentinel:
transport:
dashboard: 127.0.0.1:8090# sentinel dashboard/console 地址
port: 8719
jpa:
database: MySQL
show-sql: true
hibernate:
naming:
physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl #避免将驼峰命名转换为下划线命名
management:
endpoints:
web:
exposure:
include: "*"
# 暴露健康接口的细节
endpoint:
health:
show-details: always
Sentinel是懒加载的,在完成上述配置后,不会立刻发生变化,在发送一次请求之后,才会触发。
定义规则介绍
流控规则
阈值类型/单机阈值
- QPS(每秒钟请求数量): 当调⽤该资源的QPS达到阈值时进⾏限流
- 线程数: 当调⽤该资源的线程数达到阈值的时候进⾏限流(线程处理请求的时候,如果说业务逻辑执⾏
时间很⻓,流量洪峰来临时,会耗费很多线程资源,这些线程资源会堆积,最终可能造成服务不可⽤,
进⼀步上游服务不可⽤,最终可能服务雪崩)
是否集群: 是否集群限流
流控模式
- 直接: 资源调⽤达到限流条件时,直接限流
- 关联: 关联的资源调⽤达到阈值时候限流⾃⼰
- 链路: 只记录指定链路上的流量
流控效果
- 快速失败: 直接失败,抛出异常
- Warm Up: 根据冷加载因⼦(默认3)的值,从阈值/冷加载因⼦,经过预热时⻓,才达到设置的QPS阈值
- 排队等待: 匀速排队,让请求匀速通过,阈值类型必须设置为QPS,否则⽆效
降级规则
Sentinel会在某个资源不稳定时进行降级,在接下来的时间窗口内都进行熔断(不会像Hystrix那样放过⼀个请求尝试⾃我修复,熔断触发后,时间窗⼝内拒绝所有请求,时间窗⼝结束后才会恢复)。
- RT(平均响应时间): 当 1s 内持续进⼊ >=5 个请求,平均响应时间超过阈值(以 ms 为单位),那么在接下的时间窗口(以 s 为单位)之内,对这个⽅法的调⽤都会⾃动地熔断(抛出 DegradeException)。注意Sentinel 默认统计的 RT 上限是 4900 ms,超出此阈值的都会算作 4900 ms,若需要变更此上限可以通过启动配置项 -Dcsp.sentinel.statistic.max.rt=xxx 来配置。
- 异常比例: 当资源的每秒请求量 >= 5,并且每秒异常总数占通过量的⽐值超过阈值之后,资源进⼊降级状态,即在接下的时间窗⼝(以 s 为单位)之内,对这个⽅法的调⽤都会⾃动地返回。异常⽐率的阈
值范围是 [0.0, 1.0] ,代表 0% - 100% - 异常数: 当资源近 1 分钟的异常数⽬超过阈值之后会进⾏熔断。注意由于统计时间窗⼝是分钟级别的,若timeWindow ⼩于 60s,则结束熔断状态后仍可能再进⼊熔断状态。时间窗⼝ >= 60s
热点规则
可以通过参数在限制接口访问,针对热点数据做限流,
场景:比如一些比较火的商品,频繁访问的商品可以利用这个限流
授权规则
设置允许调用的黑白名单
系统规则
比如针对cpu占用多少时进行控制,这里是全局控制,使用的场景也比较少
Sentinel自定义兜底方法
@SentinelResource
注解类似于Hystrix中的@HystrixCommand
注解
/**
* @SentinelResource value:定义资源名
* blockHandlerClass:指定Sentinel规则异常兜底逻辑所在class类
* blockHandler:指定Sentinel规则异常兜底逻辑具体哪个⽅法
* fallbackClass:指定Java运⾏时异常兜底逻辑所在class类
* fallback:指定Java运⾏时异常兜底逻辑具体哪个⽅法
*/
@GetMapping("/checkState/{userId}")
@SentinelResource(value = "findUserState",
blockHandlerClass = SentinelFallbackClass.class,
blockHandler = "handleException",
fallback ="handleError",
fallbackClass = SentinelFallbackClass.class)
public Integer findUserState(@PathVariable Long userId) {
// 模拟降级:
/*
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
*/
// 模拟降级:异常⽐例
int i = 1 / 0;
Integer defaultUserState = resumeServiceFeignClient.findDefaultUserState(userId);
return defaultUserState;
}
⾃定义兜底逻辑类
public class SentinelHandlersClass {
// 整体要求和当时Hystrix⼀样,这⾥还需要在形参最后添加BlockException参数,⽤于接收异常
// 注意:⽅法是静态的
public static Integer handleException(Long userId, BlockException
blockException) {
return -100;
}
public static Integer handleError(Long userId) {
return -500;
}
}
Sentinel规则持久化
我们在Sentinel Dashboard中定义的规则全部存储在内存中,这会导致一个问题,当我们将Sentinel重启后,之前定义的规则就会消失,这在生产环境下对我们来说是很不方便的,我们可以借助nacos的配置中心,nacos可以将配置信息持久化到数据库,从而达到我们将Sentinel规则持久化的目的。
在微服务项目中引入依赖:
<!-- Sentinel⽀持采⽤ Nacos 作为规则配置数据源,引⼊该适配依赖 -->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
修改配置文件
server:
port: 8080
spring:
application:
name: cloud-service-user
main:
allow-bean-definition-overriding: true
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
config:
server-addr: 127.0.0.1:8848
file-extension: yaml
sentinel:
transport:
dashboard: 127.0.0.1:8090# sentinel dashboard/console 地址
port: 8719
###############################################新增部分start###################################
# Sentinel Nacos数据源配置,Nacos中的规则会自动同步到sentinel流控规则中
datasource:
# 自定义的流控规则数据源名称
flow:
nacos:
server-addr: ${spring.cloud.nacos.discovery.server-addr}
data-id: ${spring.application.name}-flow-rules
groupId: DEFAULT_GROUP
data-type: json
rule-type: flow # 类型来自RuleType类
# 自定义的降级规则数据源名称
degrade:
nacos:
server-addr: ${spring.cloud.nacos.discovery.server-addr}
data-id: ${spring.application.name}-degrade-rules
groupId: DEFAULT_GROUP
data-type: json
rule-type: degrade # 类型来自RuleType类
########################################新增部分end###########################################
jpa:
database: MySQL
show-sql: true
hibernate:
naming:
physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl #避免将驼峰命名转换为下划线命名
management:
endpoints:
web:
exposure:
include: "*"
# 暴露健康接口的细节
endpoint:
health:
show-details: always
nacos中添加对应规则配置信息
流控规则配置集 cloud-user-service-flow-rules
[
{
"resource":"findUserState",
"limitApp":"default",
"grade":1,
"count":1,
"strategy":0,
"controlBehavior":0,
"clusterMode":false
}
]
resource: 资源名称
limitApp: 来源应⽤
grade: 阈值类型 0 线程数 1 QPS
count: 单机阈值
strategy: 流控模式,0 直接 1 关联 2 链路
controlBehavior: 流控效果,0 快速失败 1 Warm Up 2 排队等待
clusterMode: true/false 是否集群
降级规则配置集 cloud-user-service-degrade-rules
[
{
"resource":"findUserState",
"grade":2,
"count":1,
"timeWindow":5
}
]
resource: 资源名称
grade: 降级策略 0 RT 1 异常⽐例 2 异常数
count: 阈值
timeWindow: 时间窗
*以上规则的可以在源码Rule接口的实现类中查看