欢迎阅读我的文章!更多精彩内容,欢迎关注:
• B站主页
:🫱小枫Geek
• 微信公众号:Procode  


        在微服务架构中,Spring Cloud Gateway 作为流量入口扮演着至关重要的角色。它不仅承担了 路由转发,还往往需要负责 限流、防刷、鉴权、安全过滤 等工作。 然而,在实际开发和部署过程中,Gateway 常常会出现一些“让人怀疑人生”的坑,比如:

  • 限流配置了却不生效,或者误伤了正常用户

  • 鉴权逻辑没问题,本地调试正常,上线后却各种 401

  • 跨域问题更是经典,调试时能用,部署后前端直接报错

        这篇文章,我将结合踩坑经历,深入解析 Spring Cloud Gateway 中 限流、鉴权与跨域 三大问题,并提供 常见原因 + 解决方案,帮助你快速避坑。


1、限流:从“不限流”到“全拦截”的玄学问题

限流是 Gateway 的常见功能,用于防止接口被恶意刷流量或高并发打挂后端服务。Spring Cloud Gateway 常见的限流实现方式有:

  • RedisRateLimiter:基于 Redis 的令牌桶限流

  • 自定义过滤器:通过 AOP 或自定义逻辑实现更灵活的限流

1.1 RedisRateLimiter 的常见坑

官方推荐的限流方式是 RedisRateLimiter,配置简单,例如:

spring:
  cloud:
    gateway:
      routes:
        - id: user_service
          uri: lb://user-service
          predicates:
            - Path=/api/user/**
          filters:
            - name: RequestRateLimiter
              args:
                redis-rate-limiter.replenishRate: 5
                redis-rate-limiter.burstCapacity: 10
                key-resolver: "#{@ipKeyResolver}"

上面配置的意思是:每秒生成 5 个令牌,最多能瞬间处理 10 个请求。

但是,常见问题来了:

问题1:限流不生效

排查方向:

  • 是否配置了 Redis 连接?

  • 是否在配置类中注册了 KeyResolver?

  • Spring Cloud 版本是否匹配?

一个常见坑是 没有注入 KeyResolver,导致限流逻辑压根没触发:

@Bean
public KeyResolver ipKeyResolver() {
    return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getHostName());
}
问题2:限流过于严格,正常请求被拦截

原因可能是:

  • burstCapacity 配置过小,瞬时高并发无法承受

  • 多个网关节点共享 Redis key 时,key 粒度过粗(例如全局 IP)

解决方案:

  • 对不同用户/接口设置不同限流规则,比如通过 userId 而非 IP 来限流

  • 合理调大 burstCapacity 以应对流量波峰

2、鉴权:明明 Token 正确却报 401?

Gateway 通常会作为统一入口负责 鉴权。常见方式有:

  • JWT 鉴权

  • OAuth2 鉴权

  • 自定义 Token 校验

2.1 本地调试正常,上线后全是 401

这个坑几乎所有人都踩过。常见原因:

  1. Header 丢失某些情况下,Gateway 默认会丢弃 Authorization 头部,导致后端服务拿不到 Token。

    解决方案:在 Gateway 的 application.yml 中显式允许保留 Header:

spring:
  cloud:
    gateway:
      default-filters:
        - PreserveHostHeader

或者在 RouteDefinition 中配置 filters,确保 Authorization 不被移除。

  1. Token 过期/时区问题

    • 本地调试时间正确,但服务器时钟不同步,JWT 过期判定提前触发。

    • 解决方案:确认服务器时间同步(NTP 服务)。

  2. 跨服务 Token 未传递如果网关把请求转发给服务 A,而服务 A 再调用服务 B,常常忘记把 Token 继续传递下去。 解决方案:在 Feign 或 RestTemplate 调用时手动传递 Authorization。

3、跨域(CORS):前端报错的万年大坑

跨域问题是前后端分离架构里最常见的“玄学 Bug”。表象通常是:

前端报错:

Access to XMLHttpRequest at 'http://api.xxx.com/user' from origin 'http://localhost:8080'
has been blocked by CORS policy

3.1 Gateway 配置跨域的正确姿势

Spring Cloud Gateway 自带的 CORS 配置如下:

spring:
  cloud:
    gateway:
      globalcors:
        corsConfigurations:
          '[/**]':
            allowedOrigins: "*"
            allowedMethods:
              - GET
              - POST
              - PUT
              - DELETE
            allowedHeaders: "*"
            allowCredentials: true

几个容易忽略的点:

  • allowedOrigins 如果配置为 *,不能再配 allowCredentials: true,否则直接报错。

  • 部署时要区分前端域名,建议不要写 *,而是配置明确的白名单,例如 https://www.xxx.com。

3.2 经典坑:OPTIONS 请求被拦截

浏览器的 CORS 预检请求是 OPTIONS,如果 Gateway 没有正确处理,跨域就失败了。

解决方案:

  • 在路由里加上 allowedMethods: OPTIONS

  • 或者在自定义过滤器里直接放行 OPTIONS 请求

if (request.getMethod() == HttpMethod.OPTIONS) {
    return chain.filter(exchange); // 直接通过
}

3.3 前端依旧报错?可能不是跨域

有时候前端报跨域错误,其实是 后端服务 500 或超时,浏览器直接以 CORS 错误兜底。 排查方法:抓包看看响应头,如果根本没有到达 Gateway,那就不是 CORS 问题,而是服务没起来。

4、如何少踩坑?

  1. 限流策略要区分维度不要一刀切按 IP 限流,可以根据用户 ID、API 级别限流,避免误伤。

  2. 鉴权要明确 Token 传递链路确认网关 → 微服务 A → 微服务 B 的 Token 是否都带过去了。

  3. 跨域配置建议精确到域名本地调试可以用 *,生产环境一定要配白名单域名,避免安全风险。

  4. 多环境测试跨域和鉴权在本地、测试环境、生产环境可能行为不同,务必全链路测试。

        Spring Cloud Gateway 功能强大,但也暗藏不少坑。 限流、鉴权、跨域这三大模块,几乎每个团队都会踩坑,但一旦理清原理,就能快速排查问题。

        如果你正在搭建微服务网关,建议在开发初期就写好 限流规则、鉴权过滤器、CORS 配置,并做压测与联调,避免上线后手忙脚乱。

更多推荐