Spring Cloud Gateway实现Rest API限流不生效及相关配置疑问
Spring Cloud Gateway限流问题解答
限流未触发根因排查
你测试时所有请求都成功未触发限流,主要是以下2个问题导致:
- 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)); }
- 限流阈值设置过高:你当前配置的
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
相关产品推荐
相关产品推荐

