You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Cloud Gateway实现Rest API限流不生效及相关配置疑问

Spring Cloud Gateway限流问题解答

限流未触发根因排查

你测试时所有请求都成功未触发限流,主要是以下2个问题导致:

  1. Redis连接配置错误:测试用例中启动了testcontainer的Redis实例,但yml中写死了Redis地址为192.168.99.100,没有绑定测试容器动态分配的地址和端口,限流组件无法正常连接Redis,默认会放行所有请求。可通过测试类新增动态配置注入修复:
@DynamicPropertySource
static void redisProperties(DynamicPropertyRegistry registry) {
    registry.add("spring.redis.host", redis::getHost);
    registry.add("spring.redis.port", () -> redis.getMappedPort(6379));
}
  1. 限流阈值设置过高:你当前配置的replenishRate为10(每秒允许10个请求)、burstCapacity为20(最大突发20个请求),测试并发为6,正常请求速率下不会触发限流,可先将两个参数调小为1、2快速验证限流效果。

疑问解答

1. 如何自定义限流触发后的错误码?

Spring Cloud Gateway默认限流返回429状态码,可通过自定义ErrorAttributes Bean修改返回状态码和响应体:

@Bean
public ErrorAttributes customRateLimitErrorAttributes() {
    return new DefaultErrorAttributes() {
        @Override
        public Map<String, Object> getErrorAttributes(ServerRequest request, ErrorAttributeOptions options) {
            Map<String, Object> attributes = super.getErrorAttributes(request, options);
            Throwable error = getError(request);
            if (error instanceof ResponseStatusException statusException 
                && statusException.getStatusCode() == HttpStatus.TOO_MANY_REQUESTS) {
                // 自定义错误码,比如改成503
                attributes.put("status", HttpStatus.SERVICE_UNAVAILABLE.value());
                attributes.put("message", "系统繁忙,请稍后重试");
                attributes.put("code", "SYS_BUSY_001");
            }
            return attributes;
        }
    };
}

2. 是否支持采集限流统计数据,查询超阈值的IP?

原生没有直接提供查询接口,但可通过两种方式实现:

  • 自定义KeyResolver时,同步将请求IP、用户标识等维度的计数存入Redis或监控系统,触发限流时打标记日志,可直接查询日志或Redis统计数据。
  • 集成Micrometer监控组件,RequestRateLimiter会自动暴露spring_cloud_gateway_request_rate_limiter指标,包含限流次数、限流key、路由ID等维度数据,对接Prometheus+Grafana即可可视化展示超阈值的IP/用户信息。

3. 限流规则是否支持Java代码配置?

yml和Java代码两种配置方式都支持,可通过注册RouteLocator Bean实现Java代码配置限流规则:

@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder, 
                                       KeyResolver userKeyResolver, 
                                       RedisRateLimiter redisRateLimiter) {
    return builder.routes()
        .route("account-service", r -> r.path("/account/**")
            .filters(f -> f.rewritePath("/account/(?<path>.*)", "/$1")
                .requestRateLimiter(conf -> {
                    conf.setKeyResolver(userKeyResolver);
                    conf.setRateLimiter(redisRateLimiter);
                })
            )
            .uri("http://localhost:8085")
        ).build();
}

还可结合配置中心实现动态限流规则加载,无需重启服务。

4. 如何验证限流触发,获取请求IP、请求量等信息?

  • 先修复Redis连接配置,调低限流阈值,测试时可打印响应头中的限流相关字段:X-RateLimit-Remaining(剩余可用请求数)、X-RateLimit-Burst-Capacity(最大突发请求数),当X-RateLimit-Remaining为0时后续请求会触发限流。
  • 自定义全局过滤器,请求进入时记录请求来源IP、请求时间、路由ID等信息,在限流异常处理逻辑中同步记录日志,即可获取所有需要的详细信息。

5. 限流参数含义说明

  • #{@userRemoteAddressResolver}:是SpEL表达式,引用Spring容器中名为userRemoteAddressResolver的Bean,作用是提取客户端IP作为限流key,实现每个IP单独计数限流。
  • Top-up rate对应配置中的replenishRate:时间单位为秒,是令牌桶的填充速率,代表每秒允许通过的请求数,设为1就是每秒向桶中放入1个令牌。
  • Bandwidth对应配置中的burstCapacity:是令牌桶的最大容量,代表允许的瞬时最大并发请求数,设为1就是桶中最多存储1个令牌,瞬时最多处理1个请求。
    比如两个参数都设为1时,每秒最多处理1个请求,超出即触发限流。

内容的提问来源于stack exchange,提问作者skyho

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 17:36:00