Sentinel:
实现熔断与限流,就是Hystrix
使用sentinel:
1,下载sentinel的jar包
2,运行sentinel
由于是一个jar包,所以可以直接java -jar运行
注意,默认sentinel占用8080端口
3,访问sentinel
localhost:8080
微服务整合sentinel:
1,启动Nacos
2,新建一个项目,8401,主要用于配置sentinel
-
pom
-
配置文件
-
主启动类
-
controller
-
到这里就可以启动8401
此时我们到sentinel中查看,发现并8401的任何信息
是因为,sentinel是懒加载,需要我们执行一次访问,才会有信息
访问localhost/8401/testA
- 可以看到.已经开始监听了
sentinel的流控规则
流量限制控制规则
流控模式:
1 + 一 直接快速失败
- 一 快速失败的源码com.alibaba.csp.sentinel.slots.block.flow.controller.DefaultController
直接失败的效果:
线程数:
比如a请求过来,处理很慢,在一直处理,此时b请求又过来了
此时因为a占用一个线程,此时要处理b请求就只有额外开启一个线程
那么就会报错
- 关联:
应用场景: 比如支付接口达到阈值,就要限流下订单的接口,防止一直有订单
当testA达到阈值,qps大于1,就让testB之后的请求直接失败
可以使用postman压测
- 链路:
多个请求调用同一个微服务
二、预热Warm up:
源码: com.alibaba.csp.sentinel.slots.block.flow.controller.WarmUpController
应用场景
三、排队等待:
源码com.alibaba.csp.sentinel.slots.block.flow.controller.RateLimiterController
降级规则:
就是熔断降级
1,RT配置:
新增一个请求方法用于测试
配置RT:
这里配置的PT,默认是秒级的平均响应时间
默认计算平均时间是:RT是平均时间(ms) 1秒内进入5个请求,并且响应的平均值超过阈值(这里的200ms),就报错。
1秒5请求是Sentinel默认设置的
测试
默认熔断后.就直接抛出异常
2,异常比例:
修改请求方法
配置:
如果没触发熔断,这正常抛出异常:
触发熔断:
3, 异常数:
一分钟之内,有5个请求发送异常,进入熔断
热点规则:
比如:
localhost:8080/aa?name=aa
localhost:8080/aa?name=b’b
加入两个请求中,带有参数aa的请求访问频次非常高,我们就现在name==aa的请求,但是bb的不限制
如何自定义降级方法,而不是默认的抛出异常?
使用@SentinelResource直接实现降级方法,它等同Hystrix的@HystrixCommand
定义热点规则:
此时我们访问/testHotkey并且带上才是p1
如果qps大于1,就会触发我们定义的降级方法
但是我们的参数是P2,就没有问题
只有带了p1,才可能会触发热点限流
2,设置热点规则中的其他选项:
需求:
测试
注意:
参数类型只支持,8种基本类型+String类
注意:
如果我们程序出现异常,是不会走blockHander的降级方法的,因为这个方法只配置了热点规则,没有配置限流规则
我们这里配置的降级方法是sentinel针对热点规则配置的
只有触发热点规则才会降级
3,系统规则:
系统自适应限流:
从整体维度对应用入口进行限流
对整体限流,比如设置qps到达100,这里限流会限制整个系统不可以
测试:
@SentinelResource注解:
用于配置降级等功能
1,环境搭建
-
为8401添加依赖
添加我们自己的commone包的依赖
- 额外创建一个controller类
-
配置限流
注意,我们这里配置规则,资源名指定的是@SentinelResource注解value的值,
这样也是可以的,也就是不一定要指定访问路径
-
测试.
可以看到已经进入降级方法了(如图资源名没有家)
-
此时我们关闭8401服务
可以看到,这些定义的规则是临时的,关闭服务,规则就没有了
可以看到,上面配置的降级方法,又出现Hystrix遇到的问题了
降级方法与业务方法耦合
每个业务方法都需要对应一个降级方法
自定义限流处理逻辑:
- 单独创建一个类,用于处理限流
- 在controller中,指定使用自定义类中的方法作为降级方法
-
Sentinel中定义流控规则:
这里资源名,是以url指定,也可以使用@SentinelResource注解value的值指定
- 测试:
- 整体:
@SentinelResource注解的其他属性:
@SentinelResource 注解
注意:注解方式埋点不支持 private 方法。
@SentinelResource
用于定义资源,并提供可选的异常处理和 fallback 配置项。 @SentinelResource
注解包含以下属性:
-
value
:资源名称,必需项(不能为空) -
entryType
:entry 类型,可选项(默认为EntryType.OUT
) -
blockHandler
/blockHandlerClass
:blockHandler
对应处理BlockException
的函数名称,可选项。blockHandler 函数访问范围需要是public
,返回类型需要与原方法相匹配,参数类型需要和原方法相匹配并且最后加一个额外的参数,类型为BlockException
。blockHandler 函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定blockHandlerClass
为对应的类的Class
对象,注意对应的函数必需为 static 函数,否则无法解析。 -
fallback
:fallback 函数名称,可选项,用于在抛出异常的时候提供 fallback 处理逻辑。fallback 函数可以针对所有类型的异常(除了exceptionsToIgnore里面排除掉的异常类型)进行处理。fallback 函数签名和位置要求:- 返回值类型必须与原函数返回值类型一致;
- 方法参数列表需要和原函数一致,或者可以额外多一个
Throwable
类型的参数用于接收对应的异常。
-
fallback 函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定
fallbackClass
为对应的类的Class
对象,注意对应的函数必需为 static 函数,否则无法解析。 -
defaultFallback
(since 1.6.0):默认的 fallback 函数名称,可选项,通常用于通用的 fallback 逻辑(即可以用于很多服务或方法)。默认 fallback 函数可以针对所有类型的异常(除了exceptionsToIgnore里面排除掉的异常类型)进行处理。若同时配置了 fallback 和 defaultFallback,则只有 fallback 会生效。defaultFallback 函数签名要求:- 返回值类型必须与原函数返回值类型一致;
- 方法参数列表需要为空,或者可以额外多一个
Throwable
类型的参数用于接收对应的异常。
-
defaultFallback 函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定
fallbackClass
为对应的类的Class
对象,注意对应的函数必需为 static 函数,否则无法解析。 -
exceptionsToIgnore
(since 1.6.0):用于指定哪些异常被排除掉,不会计入异常统计中,也不会进入 fallback 逻辑中,而是会原样抛出。
注:1.6.0 之前的版本 fallback 函数只针对降级异常(
DegradeException
)进行处理,不能针对业务异常进行处理。
特别地,若 blockHandler 和 fallback 都进行了配置,则被限流降级而抛出 BlockException
时只会进入 blockHandler
处理逻辑。若未配置 blockHandler
、fallback
和 defaultFallback
,则被限流降级时会将 BlockException
直接抛出(若方法本身未定义 throws BlockException 则会被 JVM 包装一层 UndeclaredThrowableException
)。
服务熔断:
-
启动nacos和sentinel
-
新建两个pay模块 9003和9004
-
pom
-
配置文件
-
-
主启动类
@SpringBootApplication @EnableDiscoveryClient public class PaymentMain9003 { public static void main(String[] args) { SpringApplication.run(PaymentMain9003.class,args); } }
-
controller
**然后启动9003.9004**
-
新建一个order-84消费者模块:
-
pom
与上面的pay一模一样
-
配置文件
-
- 主启动类
- 配置类
- controller
**这个时候测试如果报错了,不配置任何方法会直接显示错误页面**
- 为业务方法添加fallback来指定降级方法:
==重启order==
测试:
==所以,fallback是用于管理异常的,当业务方法发生异常,可以降级到指定方法==
注意,我们这里==并没有使用sentinel配置任何规则==,但是却降级成功,就是因为
fallback是用于管理异常的,当业务方法发生异常,可以降级到指定方法
- 为业务方法添加blockHandler,看看是什么效果
**重启84,访问业务方法:**
可以看到.,直接报错了,并没有降级
也就是说,blockHandler==只对sentienl定义的规则降级==
-
如果fallback和blockHandler都配置呢?]
设置qps规则,阈值1
测试:
可以看到,当两个都同时生效时,==blockhandler优先生效==
- @SentinelResource还有一个属性,exceptionsToIgnore
**exceptionsToIgnore指定一个异常类,**
**表示如果当前方法抛出的是指定的异常,不降级,直接对用户抛出异常**
sentinel整合ribbon+openFeign+fallback
-
修改84模块,使其支持feign
- pom
-
配置文件
-
主启动类,也要修改
- 创建远程调用pay模块的接口
- 创建这个接口的实现类,用于降级
- 再次修改接口,指定降级类
-
controller添加远程调用
-
测试
启动9003,84
-
测试,如果关闭9003.看看84会不会降级
**可以看到,正常降级了**
熔断框架比较
sentinel持久化规则
默认规则是临时存储的,重启sentinel就会消失
这里以之前的8401为案例进行修改:
-
修改8401的pom
添加: <!-- SpringCloud ailibaba sentinel-datasource-nacos 持久化需要用到--> <dependency> <groupId>com.alibaba.csp</groupId> <artifactId>sentinel-datasource-nacos</artifactId> </dependency>
-
修改配置文件:
添加:
**实际上就是指定,我们的规则要保证在哪个名称空间的哪个分组下**
这里没有指定namespace, 但是是可以指定的
注意,这里的dataid要与8401的服务名一致
- 在nacos中创建一个配置文件,dataId就是上面配置文件中指定的
json中,这些属性的含义:
- 启动8401:
可以看到,直接读取到了规则
-
关闭8401
-
此时重启8401,如果sentinel又可以正常读取到规则,那么证明持久化成功
可以看到,又重新出现了