应用背景
Sentinel提供了丰富的功能特性,如流量控制、异常熔断、集群限流和速率控制等。此外,Sentinel也提供了丰富的数据采集如RPC、HTTP以及API Gateway等。
环境配置
引入pom依赖
<!--nacos依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!--sentinel-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-transport-simple-http</artifactId>
<version>1.8.1</version>
</dependency>
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0.18.Final</version>
</dependency>
配置文件
spring:
application:
name: seckill-good # 项目名称
profiles:
active: dev # 开发环境
cloud:
nacos:
discovery:
server-addr: xxx:8848 # 注册中心的地址
config:
file-extension: yml # 文件后缀名
sentinel:
eager: true
transport:
dashboard: xxx:8080
port: 8719
配置客户端
- 下载 jar 文件
- 运行以下后,输入http://localhost:8080,打开客户端
- 若是学习sentinel,强烈将sentinel运行在本地;
java -jar sentinel-dashboard-1.8.1
流量限制的使用
虽然Sentinel提供了丰富的功能特性,但我们当下需要重点关注的是流量控制部分。所谓流量控制,其原理是监控应用流量的 QPS 或并发线程数等指标,当达到指定的阈值时对流量进行控制,以避免被瞬时的流量高峰冲垮,从而保障应用的高可用性。
请求接口添加 @SentinelResourse 接口
@GetMapping("/{activityId}/list/{itemId}")
@SentinelResource((value = "GetSeckillGood")
public BaseResponse<SeckillGoodResponse> getSeckillGood(@RequestHeader(value = "TokenInfo") Long userId,
@PathVariable Long activityId,
@PathVariable Long itemId,
@RequestParam(required = false) Long version) {
return seckillGoodService.getSeckillGood(userId, activityId, itemId, version);
}
客户端新增流控规则
测试
使用apifox启动20个线程进行测试,并不会全部成功
常见的限流策略和实现方式
限流策略
直接拒绝:对于过多的流量,直接拒绝服务即可;
异步削峰:将用户请求放入消息队列,通过异步处理的方式进行削峰,避免瞬间流量对系统造成冲击。不过要考虑队列满载和队列任务超时的情况‘
特权请求:即在服务资源紧缺的情况下,流量对部分特权用户放开,而对一般用户选择性关闭,比如你充了钱,那你可能就会享受和别人不一样的服务。
实现方式
计数器
当请求进来时,计数器加1,请求完毕后,计数器减1,当计数器的值超过阈值时,则将拒绝服务。
队列算法
待处理列表是一个队列,按FIFO算法处理到来的请求;
可以使用优先级队列,带权重的任务队列优化,处理不同的资源请求
带权重的任务队列:根据权重每次从某个队列中取出不同数量的请求,防止低权级的队列饿死
漏桶算法
水进入漏桶,就有一定的出水速率(响应速率),当水的流入速度大于溢出速度时(访问频率大于响应速率),然后就可以拒绝请求了。
出水速率是固定的参数,所以网络空闲的时候,也不能将访问频率突发到端口速率。
令牌桶算法
随着时间流逝,系统会按恒定 1/QPS 时间间隔(如果 QPS =100,则间隔是10ms)往桶里加入 Token (想象和漏洞漏水相反,有个水龙头在不断的加水),如果桶已经满了就不再加了。新请求来临时,会各自拿走一个 Token,如果没有 Token 可拿了就阻塞或者拒绝服务。
令牌桶的另外一个好处是可以方便的改变速度。一旦需要提高速率,则按需提高放入桶中的令牌的速率。一般会定时(比如100毫秒)往桶中增加一定数量的令牌,有些变种算法则实时的计算应该增加的令牌的数量。