SpringCloud Gateway限流

网关作为所有请求的入口,请求量大,我们可以通过对并发访问的请求进行限速来保护系统的可用性。

使用的是Spring Cloud Gateway作为网关,Spring Cloud Gateway 已经内置了一个RequestRateLimiterGatewayFilterFactory,目前限流RequestRateLimiterGatewayFilterFactory使用的是基于Redis的实现,我们需要增加对应的依赖:

<dependency>
<groupid>org.springframework.boot/<groupid>
<artifactid>spring-boot-starter-data-redis-reactive/<artifactid>
/<dependency>

定义Spring Cloud Gateway中的key-resolver:“#{@ipAddressKeyResolver}” #SPEL表达式去对应bean,key就是bean要取得名字,如remoteAddrKeyResolver:

IP限流:

/**
\t * 根据 HostName 进行限流
\t * @return
\t */
\t@Primary
\t@Bean(value = "remoteAddrKeyResolver")
\tpublic KeyResolver remoteAddrKeyResolver() {
\t\treturn exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getAddress().getHostAddress());
\t}

API限流:

/**
\t * 根据api接口来限流
\t * @return
\t */
\t@Bean(name="apiKeyResolver")
\tpublic KeyResolver apiKeyResolver() {
\t\treturn exchange -> Mono.just(exchange.getRequest().getPath().value());
\t}

User限流:

/**
\t * 用户限流
\t * 使用这种方式限流,请求路径中必须携带userId参数。
\t * 提供第三种方式
\t * @return
\t */
\t@Bean("userKeyResolver")
\tKeyResolver userKeyResolver() {
\t\treturn exchange -> Mono.just(exchange.getRequest().getQueryParams().getFirst("userId"));
\t}

可以根据集体情况自己添加新的限流策略

关于配置,可以在需要限流的服务中增加过滤器信息

server:
port: 20001
spring:
redis:
host: 127.0.0.1
port: 6379
cloud:
gateway:
routes:
- id: micro-activity
uri: lb://micro-activity
predicates:
- Path=/api/activity/**
filters:
- name: RequestRateLimiter //名称必须是这个
args:
redis-rate-limiter.replenishRate: 100 //允许用户每秒处理多少个请求
redis-rate-limiter.burstCapacity: 100 //令牌桶的容量,允许在一秒钟内完成的最大请求数(用的是令牌桶算法)
key-resolver: "#{@ipKeyResolver}" //使用SpEL按名称引用bean


令牌桶算法(Token Bucket)和 Leaky Bucket 效果一样但方向相反的算法,更加容易理解。随着时间流逝,系统会按恒定 1/QPS 时间间隔(如果 QPS=100,则间隔是 10ms)往桶里加入 Token(想象和漏洞漏水相反,有个水龙头在不断的加水),如果桶已经满了就不再加了。新请求来临时,会各自拿走一个 Token,如果没有 Token 可拿了就阻塞或者拒绝服务。

SpringCloud Gateway限流

令牌桶的另外一个好处是可以方便的改变速度。一旦需要提高速率,则按需提高放入桶中的令牌的速率。一般会定时(比如 100 毫秒)往桶中增加一定数量的令牌,有些变种算法则实时的计算应该增加的令牌的数量。


分享到:


相關文章: