SpringCloud Alibaba Sentinel

Sentinel 是什么?

随着微服务的流行,服务和服务之间的稳定性变得越来越重要。
Sentinel 以流量为切入点,
从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。

Sentinel 核心功能

1.流量控制

2.熔断降级

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

3.系统负载保护

- 根据系统能够处理的请求,和允许进来的请求,来做平衡,追求的目标是在系统不被
拖垮的情况下 , 提高系统的吞吐率

4.消息削峰填谷

- 某瞬时来了大流量的请求 , 而如果此时要处理所有请求,很可能会导致系统负载过高,
影响稳定性。但其实可能后面几秒之内都没有消息投递,若直接把多余的消息丢掉则没
有充分利用系统处理消息的能力
- Sentinel Rate Limiter 模式能在某一段时间间隔内以匀速方式处理这样的请求, 充分利
用系统的处理能力, 也就是削峰填谷, 保证资源的稳定性

Sentinel 控制台

1 指令 : java -jar sentinel-dashboard-1.8.0.jar
2 注意 : Sentinel 控制台 默认端口是 8080
1. 浏览器输入 : http://localhost:8080 , 用户 / 密码都是 sentinel
1 、更改 Sentinel 控制台的端口
java -jar sentinel-dashboard-1.8.0.jar --server.port=9999

将sentinel集成到微服务中(让sentinel对该服务进行实时监控)

当调用了 该 微服务时 , 可以监控到请求的 url/QPS/
响应时间 / 流量

代码/配置实现

1. 修改  微服务   pom.xml, 引入 alibaba-sentinel
< dependencies >
<!-- 引入 alibaba-sentinel -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<!-- 在微服务模块引入 nacos-discovery starter -->
< dependency >
< groupId >com.alibaba.cloud</ groupId >
< artifactId >spring-cloud-starter-alibaba-nacos-discovery</ artifactId >
</ dependency >
....
2.修改application.yml
cloud :
  nacos :
     discovery :
         server-addr : localhost:8848 # 配置 Nacos 地址
  sentinel:
     transport:
         dashboard: localhost:8080 # 这个是 sentinel 控制台 (sentinel dashboard) 的地址
#1. spring.cloud.sentinel.transport.port 端口配置会在被监控的微服务
#
对应的机器上启动一个 Http Server
#2. Server 会与 Sentinel 控制台做交互
#3. 比如 Sentinel 控制台添加了 1 个限流规则,会把规则数据 push 给这个
#
Http Server 接收, Http Server 再将规则注册到 Sentinel
#4. 简单的说明 : spring.cloud.sentinel.transport.port :指定被监控的微服务应用与
#
Sentinel 控制台交互的端口,微服务应用本地会起一个该端口占用的 Http Server
       port: 8719 # 默认 8719 ,假如被占用了 , 会自动从 8719 开始依次 +1 扫描。
# 直至找到未被占用的端口

注意事项和细节

QPS: Queries Per Second(每秒查询率),是服务器每秒响应的查询次数

Sentinel 采用的是懒加载, 只有调用了某个接口/服务,才能看到监控数据

流量控制实例-关联

当调用 member-service-nacos-provider-10004 /t2 API 接口时,如果 QPS 超过 1 ,这
时调用 /t1 API 接口 直接接失败,抛异常 .   /t2 是关联的资源 , 限流的资源是
/t1

流量控制

流量控制实例-Warm up

当流量突然增大的时候,我们常常会希望系统从空闲状态到繁忙状态的切换的时间长
一些。即如果系统在此之前长期处于空闲的状态,我们希望处理请求的数量是缓步的
增多,经过预期的时间以后,到达系统处理请求个数的最大值。 Warm Up( 冷启动,
预热 ) 模式就是为了实现这个目的的。
这个场景主要用于启动需要额外开销的场景,例如建立数据库连接等
理解机制:默认coldFactor为3,QPS从QPS阈值/3开始,经过预热逐步升至指点的QPS阈值
Warm up 称为 冷启动 /预热
应用场景 : 秒杀在开启瞬间,大流量很容易造成冲垮系统, Warmup 可慢慢的把流量放入,最
终将阀值增长到设置阀值
注:如果请求停止 ( : 一段时间没有达到阈值 ), Warm up 过程将重复 , 小伙伴可以理解是一个弹
性过程

流量控制实例-排队             

1. 排队方式:这种方式严格控制了请求通过的间隔时间,也即是让请求以均匀的速度通
过,对应的是漏桶算法
2. 这种方式主要用于处理间隔性突发的流量,例如消息队列。比如这样的场景,在某一
秒有大量的请求到来,而接下来的几秒则处于空闲状态,我们希望系统能够在接下来的
空闲期间逐渐处理这些请求,而不是在第一秒直接拒绝多余的请求。 - 类似前面说的 削
峰填谷
3.匀速排队,阈值必须设置为 QPS
4.QPS阈值=2时,每隔500ms才允许通过下一请求
5. 当调用 /API  QPS 超过 阈值   时,不拒绝请求,而是排队等待 , 依次执行
6. 当等待时间超过 10 秒,则为等待超时 .

Sentinel 熔断降级

例如:服务A调用服务B ,但是服务B不稳定导致服务A线程堆积导致服务A也崩溃。
解决:对不稳定的服务实现熔断降级,让其迅速返回结果避免线程堆积。

熔断策略:

1.慢调用比例

RT:自己设置值 若请求时间大于RT则为慢调用
比例阈值:0~1.0 慢调用请求比例 和 总请求数比
1.当一定时间内  1.请求数量> 最小请求数 2.慢调用比例 > 阈值
则接下来的时间就会进行熔断
2.当熔断时间过后会进入恢复状态,若下一个请求请求响应时间 < RT则熔断结束,若 > RT则会被再次熔断,

2.异常比例

1.请求数大于最小请求数2.异常比例 > ;比例阈值进行熔断
2.若接下来一个请求没有异常则结束熔断,否则会再次熔断

3.异常数

1.请求数大于最小请求数2.异常数目超过阈值
2.若接下来一个请求没有异常则结束熔断,否则会再次熔断

Sentinel 热点规则

引出:比如新闻热搜,在某段时间内高频访问,为了防止系统雪崩,对该条新闻进行热点限流。

热点参数限流会统计传入参数中的热点参数,对包含热点参数的资源进行限流

需求:

1.对 /news?id=x&type=x API接口进行热点限流

2.假定 id= 10 为热点新闻,当查询新闻时,对普通id (非热点新闻)请求QPS=2,如果id=10则QPS定为100

3.若访问超出QPS触发热点限流规则,调用自定义方法给出提示信息

4.降低访问量QPS达到规定范围,服务恢复

修改业务类:

/**
* 注意 @GetMapping url 带有 / , @SentinelResource value 是没有 /
* @param id
* @param type
* @return
*/
@GetMapping ( "/news" )
@SentinelResource (value = "news" ,blockHandler = "newsBlockHandler" )
public Result queryNews ( @RequestParam (value = "id" ,required = false ) String id,
@RequestParam (value = "type" ,required = false ) String type)
{
log .info( " DB 查询数据库 .... " );
return Result .success( " 返回 id= " + id + " 新闻 fromDB" );
}
// 热点 key 限制异常处理方法
public Result newsBlockHandler
( String id, String type, BlockException exception){
return Result .success( " 查询 id= " + id
+ " 新闻 触发热点 key 限制保护 .. sorry" );}
理解:1. @SentinelResource value值为自定会体现在Sentinel簇点链路中
          2. blockHandler 指定限流处理方法  "newsBlockHandler"  为同一类中的方法名

系统规则

一个问题引出系统规则

1. 如我们系统最大性能能抗 100QPS, 如何分配 /t1 /t2 QPS?

2. 方案 1 : /t1 分配 QPS=50 /t2 分配 QPS=50 , 问题 , 如果 /t1 当前 QPS 达到 50 ,
/t2 QPS 10, 会造成没有充分利用服务器性能 .
3. 方案 2 : /t1 分配 QPS=100 /t2 分配 QPS=100 , 问题 , 容易造成 系统没有流量保护,
造成请求线程堆积,形成雪崩 .
4. 有没有对各个 资源请求的 QPS弹性设置, 只要总数不超过系统最大QPS的流量保护规
则? ==> 系统规则

@SentinelResource自定义全局限流处理类

先看之前写过的限流处理类方法

@GetMapping ( "/news" )
@SentinelResource (value = "news" ,blockHandler = "newsBlockHandler" )
public Result queryNews ( @RequestParam (value = "id" ,required = false ) String id,
@RequestParam (value = "type" ,required = false ) String type) {
log .info( " DB 查询数据库 .... " );
return Result . success ( " 返回 id= " + id + " 新闻 fromDB" );
}
// 热点 key 限制异常处理方法
public Result newsBlockHandler ( String id, String type, BlockException exception){
return Result . success ( " 查询 id= " + id + " 新闻 触发热点 key 限制保护 .. sorry" );
}
说明 : 当配置的资源名 news 触发限流机制时,会调用 newsBlockHandler
方法
2. 上面的处理方案存在一些问题
  每个 @SentinelResource 对应一个异常处理方法,会造成方法很多
  异常处理方法和资源请求方法在一起,不利于业务逻辑的分离
  解决方案 -> 自定义全局限流处理类
1.创建限流处理类
public class CustomGlobalBlockHandler {
public static Result handlerMethod1 ( BlockException exception){
return Result .error( "400" , " 客户自定义异常处理 handlerm1()" );
}
public static Result handlerMethod2 ( BlockException exception){
return Result .error( "401" , " 客户自定义异常处理 handlerm2()" );
}
}
创建的异常处理方法需要是 static
2.修改controller
@GetMapping (value = "/t6" )
@SentinelResource (
value = "t6" ,
//指定限流处理类
blockHandlerClass = CustomGlobalBlockHandler . class ,
//指定处理方法
blockHandler = "handlerMethod1" )
public Result t6 () {
log .info( " 执行 t6() 线程 id= " + Thread . currentThread ().getId());
return Result . success ( "200" , "t6() 执行成功 " );
}
理解:与上一种区别将处理方法统一进行编写

fallback(@SentinelResource的一个属性)

fallback负责java异常,业务异常的返回信息

1. 需求: 请编写一个自定义全局 fallback 处理类, 处理 java 异常/业务异常

public class CustomGlobalFallbackHandler {
public static Result fallBackHandlerMethod1 ( Throwable e) {
return Result .error( "400" , "
java 异常信息 = " + e.getMessage());
}
public static Result fallBackHandlerMethod2 ( Throwable e) {
return Result .error( "401" , "
java 异常信息 = " + e.getMessage());
}
}
2.修改controller
@GetMapping (value = "/t6" )
@SentinelResource (
value = "t6" ,
fallbackClass = CustomGlobalFallbackHandler.class,
fallback = "fallBackHandlerMethod1",
blockHandlerClass = CustomGlobalBlockHandler . class ,
blockHandler = "handlerMethod1"
)
public Result t6 () {
if (++ num % 5 == 0 ) { // 假定 : 当访问 t6 资源次数是 5 的倍数时,就出现了一个 java 的异
throw new RuntimeException( "num 的值异常 num= " + num );
}
log .info( " 执行 t6() 线程 id= " + Thread . currentThread ().getId());
return Result . success ( "200" , "t6() 执行成功 " );
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值