如何限流?在工作中是怎么做的?说一下具体的实现?

什么是限流

限流可以认为服务降级的一种,限流就是限制系统的输入和输出流量已达到保护系统的目的。

一般来说系统的吞吐量是可以被测算的,为了保证系统的稳定运行,一旦达到的需要限制的阈值,就需要限制流量并采取一些措施以完成限制流量的目的。

比如:延迟处理,拒绝处理,或者部分拒绝处理等等。

工作中的使用

spring cloud gateway

spring cloud gateway 默认使用 redis 进行限流,笔者一般只是修改修改参数属于拿来即用,并没有去从头实现上述那些算法。

  [xml]
1
2
3
4
5
6
7
8
<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>
  [yml]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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
  [java]
1
2
3
4
@Bean KeyResolver remoteAddrKeyResolver() { return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getHostName()); }

sentinel

通过配置来控制每个 url 的流量

  [xml]
1
2
3
4
<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> </dependency>
  [yml]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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 上进行编辑

  [json]
1
2
3
4
5
6
7
8
9
10
11
[ { "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