计数器算法是通过维护一个单位时间内的计数器,每次请求计数器+1,当单位时间累加的计数器超过设置的阈值,则之后的请求全部拒绝,直到单位时间过去,把计数器清0
缺点:不能平滑的限流,如1分钟限制请求50次,在10秒时达到请求上线,则从11-60之间的所有请求全部拒绝
漏桶算法可以很好的控制容容量池的大小,从而防止流量暴增。漏桶可以看成一个服务队列,如果漏桶溢出,则请求会被丢弃。漏桶算法可以控制流量输出速率,实现流量整形,平滑流量突发情况。 漏桶算法有2个变量需要控制,一个是桶的大小,一个是流量输出速率
令牌桶算法是对漏桶算法的改进,存在一个桶用来存放固定数量的令牌。算法中存在一种机制,以一定的速率给桶中放入令牌,每次请求需要先获取令牌,只有获取到令牌的请求可以继续请求微服务,否则等待令牌或者丢弃请求。放令牌的动作是持续进行的,如果令牌桶中令牌达到上限,就会丢弃令牌。
Springcloud gateway官方提供了基于令牌桶的限流算法,基于内部的过滤器工厂RequestRateLimiterGatewayFilterFactory实现。在过滤器工厂内部是通过Redis和lua脚本结合的方式进行流量控制
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis-reactive</artifactId> </dependency> 复制代码
spring: application: name: microservice-gateway redis: host: localhost port: 6379 database: 0 cloud: gateway: routes: #设置路由:路由id、路由打微服务的uri、断言 - id: microservice-provider #路由ID,全局唯一 # uri: http://127.0.0.1:8001 #目标微服务的请求地址和端口 uri: lb://microservice-provider # lb://微服务名 根据微服务名称从注册中心获取地址 predicates: - Path=/product/** #路由条件,采用path路由规则 filters: # 实现重写转发路径: http://localhost:6101/product/provider/list --> http://localhost:6101/provider/list - RewritePath=/product/(?<segment>.*), /$/{segment} - name: RequestRateLimiter args: redis-rate-limiter.replenishRate: 1 #令牌桶每秒放入速率 redis-rate-limiter.burstCapacity: 3 #令牌桶的上限 # key-resolver: "#{@pathKeyResolver}" #基于请求路径的限流解析 key-resolver: "#{@userKeyResolver}" #基于请求参数的限流解析 复制代码
@Configuration @Log4j2 public class KeyResolverConfiguration { /** * 基于请求路径的限流规则 */ @Bean public KeyResolver pathKeyResolver() { return new KeyResolver() { @Override public Mono<String> resolve(ServerWebExchange exchange) { return Mono.just(exchange.getRequest().getPath().toString()); } }; } /** * 基于请求参数限流 */ @Bean public KeyResolver userKeyResolver() { return exchange -> Mono.just( exchange.getRequest().getQueryParams().getFirst("userId") ); } } 复制代码