spring cloud gateway配置请求限流
一、原理介绍
- spring cloud gateway内置的限流器使用的是令牌桶算法(Token Bucket),它是目前应用最广泛的一种限流算法,它的基本思想由两部分组成:生成令牌 和 消费令牌。
- 生成令牌:假设有一个装令牌的桶,最多能装 M 个,然后按某个固定的速度(每秒 r 个)往桶中放入令牌,桶满时不再放入;
- 消费令牌:我们的每次请求都需要从桶中拿一个令牌才能放行,当桶中没有令牌时即触发限流,这时可以将请求放入一个缓冲队列中排队等待,或者直接拒绝;
- 令牌桶算法的图示如下:(图片来源:https://blog.csdn.net/weixin_38405253/article/details/108891772)
![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/699fe60020a74f04a8bd2329bd41c6ad.png)
二、项目实践
- 打开我们的spring cloud gateway项目,进入pom.xml配置必要的依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
- 在路由中配置限流规则
spring:
cloud:
gateway:
discovery:
locator:
lowerCaseServiceId: true
enabled: true
routes:
- id:
uri: lb://
predicates:
- Path=/api-uaa/oauth/token
filters:
- StripPrefix=1
- PreserveHostHeader
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 10
redis-rate-limiter.burstCapacity: 20
key-resolver: "#{@hostAddrKeyResolver}"
- id:
uri: lb://
predicates:
- Path=/api-uaa/**
filters:
- StripPrefix=1
- PreserveHostHeader
- 配置限流规则中的分组id,这个类不需要深究,就是个通用的配置
package com.central.gateway.filter;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import reactor.core.publisher.Mono;
@SpringBootConfiguration
public class RequestRateLimiterConfig {
@Bean
@Primary
public KeyResolver hostAddrKeyResolver() {
return (exchange) -> Mono.just(exchange.getRequest().getRemoteAddress().getHostName());
}
@Bean
public KeyResolver userKeyResolver() {
return exchange -> Mono.just(exchange.getRequest().getQueryParams().getFirst("userId"));
}
@Bean
public KeyResolver apiKeyResolver() {
return exchange -> Mono.just(exchange.getRequest().getPath().value());
}
}
文章的内容都是个人看法,如果不对之处,烦请指出,先行谢过。
文章借鉴了https://www.jb51.net/article/267798.htm、https://blog.csdn.net/weixin_38405253/article/details/108891772,这两篇文章写的很好,非常感谢他们。