如何在项目中添加Sentinel的支持请看这里
Sentinel笔记(一)第一个监控实例
流量监控规则
- 资源名:唯一名称,默认请求路径
- 针对来源:Sentinel可以针对调用者进行限流,填写微服务名,指定对哪个微服务进行限流 ,默认default(不区分来源,全部限制)
- 阈值类型/单机阈值:
- QPS(每秒钟的请求数量):当调用该接口的QPS达到了阈值的时候,进行限流;
- 线程数:当调用该接口的线程数达到阈值时,进行限流
- 是否集群:不需要集群
- 流控模式:
- 直接:接口达到限流条件时,直接限流
- 关联:当关联的资源达到阈值时,就限流自己
- 链路:只记录指定链路上的流量(指定资源从入口资源进来的流量,如果达到阈值,就可以限流)【api级别的针对来源】
- 流控效果
- 快速失败:直接失败,抛出异常
- Warm Up:根据coldFactor(冷加载因子,默认3)的值,从阈值/coldFactor,经预热时长逐渐升至设定的 QPS 阈值
- 排队等待:匀速排队,让请求以均匀的速度通过,阈值类型必须设置为QPS,否则无效
添加流控规则两种方式
第一种在已知的簇点链路上添加
第二种在流控规则菜单内自定义添加
创建第一个流控规则(QPS快速失败)
新增如下规则
对/test/a
资源设置QPS每秒1次的限制
流控模式:直接
流控效果:快速失败
意思就是如果每秒超过1次以上的访问会直接限流并返回失败
保存后可以在流控规则列表里面看到刚刚配置的规则,并且可以在这里进行修改和删除
测试一下
疯狂访问 http://localhost:8401/test/a
成功出现默认的失败信息
流控模式
基于线程的快速失败
创建以下配置,表示同时访问的线程数超过1就直接失败
针对于线程来说,直接就是快速失败,在直接下面没有其他的高级选项
测试:我们需要先修改testB()方法,让其在内部休眠800ms,要是不这么搞的话就这个方法用手点刷新累死也超不过一个线程
@GetMapping("/test/b")
public String TestB(){
try {
TimeUnit.MILLISECONDS.sleep(800L);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "======Test B========";
}
点快一点总会成功的,哈哈
由于线程数的流控效果只有快速失败,后面的流控模式统一用QPS进行测试
关联
关联:当关联的资源达到阈值时,就限流自己
创建如下图的配置,就是当资源/test/b
的QPS超过每秒一次,那么就限制/test/a
接口
testB()方法改回来
@GetMapping("/test/b")
public String TestB(){
return "======Test B========";
}
使用PostMan进行测试,要不然我们来回切很麻烦
创建请求,先测试接口是否能访问成功,能正常访问后点击Save或者右边的小三角SaveAs
弹出表单,点+ Create Collection
,然后起名保存就可以了,我这起名test
然后主界面左侧菜单切换到Collections就能看到了,鼠标放到我们创建的 test 这一栏,右边出现小三角,点击小三角就可以配置请求次数,请求间隔等参数了
小三角点出菜单后点击run
然后出来界面后填入,20次请求,每隔300ms一次,点击Run test
运行后,马上去浏览器访问
http://localhost:8401/test/a
,如期出现失败
链路
从簇点链路的树状视图可以看到,sentinel_web_servlet_context 为 /test/a 的入口资源
创建下面的配置,如果从 sentinel_web_servlet_context 走到 /test/a 的请求QPS大于1,那么就失败
保存后测试,疯狂访问 http://localhost:8401/test/a
就会返回失败
流控效果
直接失败
前面的例子也是用了直接失败了,这里就不再演示了
Sentinel里面直接失败的源码来自下面这个类,感兴趣的可以看一下
com.alibaba.csp.sentinel.slots.block.flow.controller.DefaultController
Warm Up(预热)
Warm Up:根据coldFactor(冷加载因子,默认3)的值,从阈值/coldFactor,经预热时长逐渐升至设定的 QPS 阈值
解释:coldFactor默认值为3,假设我们设定 QPS 或线程为 10,那么初始可以接受的最大值就为10 / 3 = 3
,将预热时长设置为 5 秒,那么 5 秒之内慢慢升到每秒可接受的最大值 10
预热是因为某个接口平时处于低访问量的情况下没有问题,突然大批量的请求打进来,防止服务崩掉,让它慢慢升至可接受的最大值
为了不受前面例子的影响,我这里先将之前的流控规则删掉,然后创建以下规则,就创建个和上面解释里面一样的例子
新增后访问http://localhost:8401/test/a
匀速点击刷新或者F5,刚开始要超过一秒三次(一般人都能做到),就能看见返回的失败了,慢慢的返回失败的减少,直到全部返回成功,反正我是一秒点不上十次,哪位大哥手速够快可以试试五秒后超过十次
排队等待
排队等待:匀速排队,让请求以均匀的速度通过,阈值类型必须设置为QPS,否则无效
算法:漏桶算法
单机阈值:一秒可以接受的最大请求数,超过设置的就去排队
超时时间:每个请求可以在队列中多久,超过这个时间就不排队了,返回失败
依旧删除之前的规则,创建以下规则:每秒处理一个请求,如果某个请求在队列中等待超过20秒就返回失败,这里的时间单位和预热不同,预热是秒,这里是毫秒,需要注意一下
改一下testA()接口,先在controller上添加注解 @Slf4j 用来记日志
@Slf4j
public class FlowLimitController
然后testA里面记一下日志,log会自动帮助我们记录时间
@GetMapping("/test/a")
public String TestA(){
log.info(Thread.currentThread().getName() + "\t" + "/test/a");
return "======Test A========";
}
用PostMan创建一个压测,访问testA接口,10个请求,100ms一次,没限流应该就是一秒十次完事,所以我们这里可以看看日志是不是一秒输出一次就行了
可以看到控制台输出,非常稳定的一秒一次
总结
至此,所有的流控规则就写完了,Sentinel可以流控规则覆盖场景可以说是非常全面了,具体使用那种规则要看实际的业务场景来定