如何限流?在工作中是怎么做的?说一下具体的实现?
什么是限流
限流可以认为服务降级的一种,限流就是限制系统的输入和输出流量已达到保护系统的目的。
一般来说系统的吞吐量是可以被测算的,为了保证系统的稳定运行,一旦达到的需要限制的阈值,就需要限制流量并采取一些措施以完成限制流量的目的。
比如:延迟处理,拒绝处理,或者部分拒绝处理等等。
工作中的使用
spring cloud gateway
spring cloud gateway 默认使用 redis 进行限流,笔者一般只是修改修改参数属于拿来即用,并没有去从头实现上述那些算法。
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>
spring:
cloud:
gateway:
routes:
- id: requestratelimiter_route
uri: lb://pigx-upms
order: 10000
predicates:
- Path=/admin/**
filters:
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 1 # 令牌桶的容积
redis-rate-limiter.burstCapacity: 3 # 流速 每秒
key-resolver: '#{@remoteAddrKeyResolver}' #SPEL表达式去的对应的bean
- StripPrefix=1
@Bean
KeyResolver remoteAddrKeyResolver() {
return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getHostName());
}
sentinel
通过配置来控制每个 url 的流量
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
spring:
cloud:
nacos:
discovery:
server-addr: localhost:8848
sentinel:
transport:
dashboard: localhost:8080
port: 8720
datasource:
ds:
nacos:
server-addr: localhost:8848
dataId: spring-cloud-sentinel-nacos
groupId: DEFAULT_GROUP
rule-type: flow
namespace: xxxxxxxx
配置内容在 nacos 上进行编辑
[
{
"resource": "/hello",
"limitApp": "default",
"grade": 1,
"count": 1,
"strategy": 0,
"controlBehavior": 0,
"clusterMode": false
}
]
-
resource:资源名,即限流规则的作用对象。
-
limitApp:流控针对的调用来源,若为 default 则不区分调用来源。
-
grade:限流阈值类型,QPS 或线程数模式,0 代表根据并发数量来限流,1 代表根据 QPS 来进行流量控制。
-
count:限流阈值
-
strategy:判断的根据是资源自身,还是根据其它关联资源 (refResource),还是根据链路入口
-
controlBehavior:流控效果(直接拒绝 / 排队等待 / 慢启动模式)
-
clusterMode:是否为集群模式
总结
sentinel 和 spring cloud gateway 两个框架都是很好的限流框架, 但是在我使用中还没有将spring-cloud-alibaba接入到项目中进行使用, 所以我会选择spring cloud gateway, 当接入完整的或者接入 Nacos 项目使用 setinel 会有更加好的体验.
参考资料
https://github.com/doocs/advanced-java/blob/main/docs/high-concurrency/how-to-limit-current.md