SpringCloud:Sentinel实现熔断与限流(2)

热点key限流 / 系统规则(系统自适应限流)/ @SentinelResource 注解详解 /  服务熔断 / 持久化规则

1.热点key限流

官方文档:https://github.com/alibaba/Sentinel/wiki/%E7%83%AD%E7%82%B9%E5%8F%82%E6%95%B0%E9%99%90%E6%B5%81

热点参数限制会统计传入参数中的热点参数,并根据配置的限流阈值与模式,对包含热点参数的资源调用进行限制。热点参数限流可以看作是一种特殊的流量控制,仅对包含热点参数的资源调用生效。

  • 商品 ID 为参数,统计一段时间内最常购买的商品 ID 并进行限制
  • 用户 ID 为参数,针对一段时间内频繁访问的用户 ID 进行限制
SpringCloud:Sentinel实现熔断与限流(2)

1.1基本使用

兜底防范分为系统默认和客户自定义:

  1. sentinel系统默认的提示:Blocked by Sentinel (flow limiting)。
  2. 类似于@HystrixCommand, 引入@SentinelResource注解。
SpringCloud:Sentinel实现熔断与限流(2)

资源名:唯一路径,默认为请求路径。此处必须是 @SentinelResource 注解的 value 属性值,配置@GetMapping 的请求路径无效)

1.1.1测试方法

在8401的controller中,加入热点测试方法。

@SentinelResource注解分析

  • 其中 value = “testHotKey” 是一个标识(Sentinel资源名),与rest的`/testHotKey`对应,这里value的值可以任意写,但是我们约定与rest地址一致,唯一区别是没有`/`。
  • blockHandler = “del_testHotKey” 则表示如果违背了Sentinel中配置的流控规则,就会调用我们自己的兜底方法del_testHotKey

1.1.2配置热点key限流规则

方法testHotKey里面第一个参数只要QPS超过每秒1次,马上降级处理

SpringCloud:Sentinel实现熔断与限流(2)

1.1.3 测试

  • 1次/s正常显示,迅速点击两次,触发热点限流,执行自定义兜底方法:http://127.0.0.1:8401/testHotKey?p1=a
  • 仅传入参数p2没有任何影响: http://localhost:8401/testHotKey?p2=b
  • 个通过jmeter压测http://localhost:8401/testHotKey?p1=a&p2=b,另外再单独使用浏览器访问http://localhost:8401/testHotKey?p2=b,发现只带参数p2访问没有任何影响。

参数例外项

期望p1参数当它是某个特殊值时,它的限流值和平时不一样,比如当p1的值等于5时,它的阈值可以达到200。

SpringCloud:Sentinel实现熔断与限流(2)

狂点http://localhost:8401/testHotKey?p1=5&p2=b 没有限流

其他

手动添加一个异常:

SpringCloud:Sentinel实现熔断与限流(2)

测试直接错误页面。

Sentinel它只管你有没有触发它的限流规则,也可以说只管这个web交互页面(控制台)里面的东西。 配置类的东西Sentinel可以管,java异常的错误Sentinel不管。

总结:
@SentinelResource主管配置出错,运行出错该走异常走异常

2.系统规则(系统自适应限流)

SpringCloud:Sentinel实现熔断与限流(2)

Sentinel 系统自适应限流从整体维度对应用入口流量进行控制,(让系统尽可能跑在最大吞吐量的同时保证系统整体的稳定性。)

  • Load 自适应(仅对 Linux/Unix-like 机器生效):系统的 load1 作为启发指标,进行自适应系统保护。当系统 load1 超过设定的启发值,且系统当前的并发线程数超过估算的系统容量时才会触发系统保护(BBR 阶段)。系统容量由系统的 maxQps * minRt 估算得出。设定参考值一般是 CPU cores * 2.5。
  • CPU usage(1.5.0+ 版本):当系统 CPU 使用率超过阈值即触发系统保护(取值范围 0.0-1.0),比较灵敏。
  • 平均 RT:当单台机器上所有入口流量的平均 RT 达到阈值即触发系统保护,单位是毫秒。
  • 并发线程数:当单台机器上所有入口流量的并发线程数达到阈值即触发系统保护。
  • 入口 QPS:当单台机器上所有入口流量的 QPS 达到阈值即触发系统保护。

如把入口QPS设置为1,不管是/testA还是/testB 只要QPS > 1 整个系统就不能用。

3.@SentinelResource 注解详解

3.1按资源名称限流+后续处理

3.1.1 修改8401

(1) pom

引入我们自定义的公共api jar包

(2) 业务类

RateLimitController

3.1.2 配置流控规则——按资源名称添加流控规则

SpringCloud:Sentinel实现熔断与限流(2)

3.1.3测试

自测:

SpringCloud:Sentinel实现熔断与限流(2)

触发流控规则:

SpringCloud:Sentinel实现熔断与限流(2)

3.1.4 问题

如果我们重启8401会发现之前配置的一些规则都没有了。难道每次重启服务器都要重新配置一遍规则吗?规则如何进行持久化?

8.2 按照Url地址限流+后续处理

通过访问的URL来限流,会返回Sentinel自带默认的限流处理信息

修改业务层

按rest URI设置流控规则后,触发流控规则:

SpringCloud:Sentinel实现熔断与限流(2)

3.3 总结以及面临的问题

  • 依照现有条件,我们自定义的处理方法又和业务代码耦合在一块,不直观。如果都用系统默认的,就没有体现我们自己的业务要求。
  • 如果每个业务方法/API接口都添加一个兜底的,那代码膨胀加剧。
  • 全局统一的处理方法没有体现。

3.4 客户自定义限流处理逻辑

为了解决代码耦合与膨胀的问题

3.4.1创建CustomerBlockHandler类用于自定义限流处理逻辑(单独放在一个包里)

3.4.2 修改RateLimitController,使用自定义处理逻辑类

SpringCloud:Sentinel实现熔断与限流(2)

3.4.3 测试

设置流控,触发流控后:

SpringCloud:Sentinel实现熔断与限流(2)

3.5 更多属性说明

文档:https://github.com/alibaba/Sentinel/wiki/%E6%B3%A8%E8%A7%A3%E6%94%AF%E6%8C%81

SpringCloud:Sentinel实现熔断与限流(2)

4.服务熔断

主要内容:

  • sentinel分别整合ribbon+openFeign以及设置fallback
  • 熔断框架比较

4.1 Ribbon系列

nacos中整合了Ribbon,所以直接使用nacos就行。启动nacos和Sentinel。

fallback和blockHandler

fallback管运行异常,blockHandler管配置违规。
fallback对应服务降级,就是服务出错了应该怎么办(需要有个兜底方法);
blockHandler对应服务熔断,就是我现在服务不可用,我应该怎么办,怎么给客户一个户提示(同样需要一个兜底方法)

SpringCloud:Sentinel实现熔断与限流(2)

同时配置fallback:处理业务异常(微服务自身异常,服务降级)和blockHandler:处理触发sentinel配置(微服务不可用,服务熔断)时。在没有违反sentinel规则时,出现业务异常(降级)走fallback方法;违反了sentinel规则时,直接微服务不可用(熔断),走blockHandler指定的自定义方法。

也就是说 有java异常的同时,也违反sentinel规则,此时会走blockHandler(熔断)

异常忽略属性

SpringCloud:Sentinel实现熔断与限流(2)

即出现指定的异常,不执行兜底方法,而是直接返回错误页面!

当然,触发流控之后,仍然通过blockHandler指定的方法进行熔断兜底。

Feign系列

修改消费者模块

(1) pom

加入feign的依赖

(2) yml

激活Sentinel对Feign的支持

(3) 业务类

后续84的controller不找restTemplate(Ribbon),不是restTemplate去调用payment微服务中的接口。而是通过调用PaymentFeignService,service再去调用payment微服务中的端口。

Feign需要定义一个业务逻辑(service)接口+ @FeignClient注解以调用服务提供者。
新建PaymentFeignService interface:

PaymentFeignService

调用失败的兜底方法:PaymentFallbackService

controller加入openFeign的接口:

(4) 主启动类
加上@EnableFeignClient注解开启OpenFeign

(5) 测试

SpringCloud:Sentinel实现熔断与限流(2)

熔断框架比较

SpringCloud:Sentinel实现熔断与限流(2)

5.持久化规则

前面我们微服务新增的限流规则后,微服务关闭后就会丢失,当时配置都限流规则都是临时的。

案例——修改8401已完成持久化设置

(1) pom.

导入持久化所需依赖

(2) yaml

application.yaml

(3) 添加nacos业务规则配置

我们将sentinel的流控配置保存在nacos中,因为nacos的配置持久化在了数据库中。

SpringCloud:Sentinel实现熔断与限流(2)

resource:资源名称;
limitApp:来源应用;
grade:阈值类型,0表示线程数,1表示QPS;
count:单机阈值;
strategy:流控模式,0表示直接,1表示关联,2表示链路;
controlBehavior:流控效果,0表示快速失败,1表示Warm Up,2表示排队等待;
clusterMode:是否集群。

注意:这里如果要配nacos的命名空间(public、dev、test)的话,应该是配namespace的id,不是名称

(4) 测试

启动8401,访问8401任意接口,刷新Sentinel。可以看到Sentinel中加载了通过nacos持久化的规则配置文件

关掉8401后发现流控规则没有了

再次启动8401查看sentinel,访问几次8401后流控规则又出现了。
查看数据库,发现规则持久化到数据库中了。

正文完
 0