六:Gateway网关限流


  gateway默认给我们提供了限流实现,也就是网关拦截器RequestRateLimiter。

6.1 令牌桶限流算法 RequestRateLimiter底层实现是令牌桶算法;

  令牌桶内存储令牌,令牌桶需要设置令牌容量,也就是系统最大的并发大; 以一定的速率生成令牌(具体速率根据系统性能设置),放到令牌桶,如果桶慢了,则丢弃; 客户端来一个请求,则先去令牌桶获取令牌,拿到令牌,则处理请求,否则 丢弃或者返回失败;

 令牌桶算法的优点:
  (1)通过恒定的速率生成令牌桶,能够让请求处理更均匀,不会出现短时间大量的请求处理;
  (2)比较友好的控制高并发;  
page16image24291456

page17image9779312

6.2 Gateway网关限流实例
  Spring Cloud Gateway官方提供了 RequestRateLimiterGatewayFilterFactory 过滤器工厂,使用Redis 和 Lua 脚本实现了令牌桶,来实现网关限流; 添加下Redis依赖:

 
    org.springframework.boot
    spring-boot-starter-data-redis

 
    org.apache.commons
    commons-pool2

6.2.1 URI限流 

配置类:

package com.java1234.config;
import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import reactor.core.publisher.Mono;
/**
* 限流规则配置类
* @author java1234
*/
@Configuration
public class KeyResolverConfiguration {
    @Bean
    public KeyResolver pathKeyResolver(){
        /*return new KeyResolver() {
            @Override
            public Mono resolve(ServerWebExchange exchange) {
                return Mono.just(exchange.getRequest().getURI().getPath());
} };*/
return exchange -> Mono.just(exchange.getRequest().getURI().getPath()); // URI限流
} }

yml配置:

spring:
  application:
    name: gateway-server
  cloud:
    gateway:
      routes:
        - id: rateLimiter
          uri: http://localhost:8080/
          predicates:
           - Path=/product/**
          filters:
           - name: RequestRateLimiter # 限流过滤器 
             args:            
                    redis-rate-limiter.replenishRate: 1 # 令牌桶每秒填充速率 r
            redis-rate-limiter.burstCapacity: 2 # 令牌桶总容量 
            redis-rate-limiter.requestedTokens: 1 # 一个请求需要消费的令牌数
            key-resolver: "#{@pathKeyResolver}"   redis: # redis配置     host: 192.168.0.103 # IP     port: 6379 # 端口     password: # 密码     connect-timeout: 10s # 连接超时时间
    lettuce: # lettuce redis客户端配置       pool: # 连接池配置         max-active: 8 # 连接池最大连接数(使用负值表示没有限制) 默认 8
        max-wait: 200s # 连接池最大阻塞等待时间(使用负值表示没有限制) 默认 -1
        max-idle: 8 # 连接池中的最大空闲连接 默认 8         min-idle: 0 # 连接池中的最小空闲连接 默认 0

访问过多之后,报429错误;

page19image27011232page19image27014768

6.2.2 参数限流 配置类:

package com.java1234.config;
import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import reactor.core.publisher.Mono;
/**
* 限流规则配置类
* @author java1234
*/
@Configuration
public class KeyResolverConfiguration {
    @Bean
    public KeyResolver parameterKeyResolver(){
        /*return new KeyResolver() {
            @Override
            public Mono resolve(ServerWebExchange exchange) {
                return
Mono.just(exchange.getRequest().getQueryParams().getFirst("token"));
            }
};*/
return exchange -> Mono.just(exchange.getRequest().getQueryParams().getFirst("token")); // 参数限流
} }

请求带一个参数:http://localhost/product/32?token=fdafa

page20image24445120 page20image27007904

6.2.3 IP限流 配置类:

 
package com.java1234.config;


import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; /** * 限流规则配置类 * @author java1234 */ @Configuration public class KeyResolverConfiguration { @Bean public KeyResolver ipKeyResolver(){ /*return new KeyResolver() { @Override public Mono resolve(ServerWebExchange exchange) { return Mono.just(exchange.getRequest().getRemoteAddress().getHostName()); } };*/ return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getHostName()); // IP限流 } }