Spring Cloud Gateway程序员简友广场

Spring Cloud Gateway(二、请求限流)

2020-08-07  本文已影响0人  梅西爱骑车

一、前言

Spring Cloud Gateway 内置 RequestRateLimiterGatewayFilterFactory 提供请求限流的功能。该 Filter 是基于 Token Bucket Algorithm(令牌桶算法)实现的限流,同时搭配上 Redis 实现分布式限流

对于很多应用场景来说,除了要求能够限制数据的平均传输速率外,还要求允许某种程度的突发传输。这时候漏桶算法可能就不合适了,令牌桶算法更为适合。如下图所示,令牌桶算法的原理是系统会以一个恒定的速度往桶里放入令牌,而如果请求需要被处理,则需要先从桶里获取一个令牌,当桶里没有令牌可取时,则拒绝服务。

令牌桶算法示意图

二、引入依赖

修改 [pom.xml]文件,引入相关的依赖如下:

    <dependencies>
        <!-- 引入 Spring Cloud Gateway 相关依赖,使用它作为网关,并实现对其的自动配置 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>

        <!-- 实现对 Spring Data Redis 的自动化配置 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

    </dependencies>

三、配置文件

修改 [application.yaml]配置文件,增加限流 Filter 的配置项。完整配置如下:

server:
  port: 8888

spring:
  application:
    name: sc-gateway-application

  cloud:
    ## Spring Cloud Gateway 配置项,对应 GatewayProperties 类
    gateway:
      # 路由配置项,对应 RouteDefinition 数组
      routes:
        - id: erbadagang_rate_limiter # 路由的编号
          uri: https://www.jianshu.com/u/ea0462d5074c # 路由到的目标地址(我的简书主页地址)
          predicates: # 断言,作为路由的匹配条件,对应 RouteDefinition 数组
            - Path=/jianshu
          filters:
            - StripPrefix=1
            - name: RequestRateLimiter
              args:
                redis-rate-limiter.replenishRate: 1 # 令牌桶的每秒放的数量
                redis-rate-limiter.burstCapacity: 2 # 令牌桶的最大令牌数
                key-resolver: "#{@ipKeyResolver}" # 获取限流 KEY 的 Bean 的名字
        - id: guo # 路由的编号
          uri: https://www.126.com # 路由的目标地址
          predicates: # 断言,作为路由的匹配条件,对应 RouteDefinition 数组
            - Path=/*
          filters: # 过滤器,对请求进行拦截,实现自定义的功能,对应 FilterDefinition 数组
            - StripPrefix=1

  ##### Redis 配置项 #####
  redis:
    host: 127.0.0.1
    port: 6379

① 针对编号为 erbadagang_rate_limiter 的路由,我们在 filter 配置项,添加了限流过滤器 RequestRateLimiter,其配置参数如下:

spring.redis 配置项,设置使用的 Redis 的配置。

有一点要注意,使用的 Redis 客户端需要提供 Reative 的操作,目前能够支持的是 Lettuce 和 Redisson,也就是说我们暂时不能使用 Jedis。

四、GatewayConfig

创建获取限流 KEY 的 Bean。代码如下:

package com.erbadagang.springcloud.gateway.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;

/**
 * @description 限流 KEY 的 Bean ,通过解析请求的来源 IP 作为限流 KEY,这样我们就能实现基于 IP 的请求限流。
 * @ClassName: GatewayConfig
 * @author: 郭秀志 jbcode@126.com
 * @date: 2020/7/29 15:26
 * @Copyright:
 */
@Configuration
public class GatewayConfig {

    @Bean
    public KeyResolver ipKeyResolver() {
        return new KeyResolver() {

            @Override
            public Mono<String> resolve(ServerWebExchange exchange) {
                // 获取请求的 IP
                return Mono.just(exchange.getRequest().getRemoteAddress().getHostName());
            }

        };
    }

}

创建的 ipKeyResolver Bean 是通过解析请求的来源 IP 作为限流 KEY,这样我们就能实现基于 IP 的请求限流。

如果说,我们想要实现基于用户的请求限流,那么我们可以创建从请求中解析用户身份的 KeyResolver Bean。也就是说,通过自定义的 KeyResolver 来实现不同粒度的请求限流。

五、 简单测试

  1. 启动Redis
  2. 执行 GatewayApplication, 启动网关代码。
  3. 使用浏览器,连续快速访问 http://127.0.0.1:8888/jianshu 地址,将会出现被限流为空白页。

底线


本文源代码使用 Apache License 2.0开源许可协议。可通过git clone命令从代码的Gitee仓库地址获取代码到本地,或者直接点击链接通过浏览器方式查看源代码。

上一篇 下一篇

猜你喜欢

热点阅读