Spring Cloud Gateway 实战:构建高可用微服务 API 网关的五个关键设计

举报
yd_286050264 发表于 2026/10/29 20:06:33 2026/10/29
【摘要】 在微服务架构演进中,服务拆分带来了独立部署与弹性伸缩的红利,也引入了一个绕不开的问题:外部客户端该如何与数十乃至上百个内部服务通信?直接暴露所有服务显然不可行,API 网关因此成为微服务体系的"统一入口"。

在微服务架构演进中,服务拆分带来了独立部署与弹性伸缩的红利,也引入了一个绕不开的问题:外部客户端该如何与数十乃至上百个内部服务通信?直接暴露所有服务显然不可行,API 网关因此成为微服务体系的"统一入口"。Spring Cloud Gateway 基于 Spring WebFlux 与 Reactor 实现非阻塞 IO,在吞吐与资源占用上相较传统 Zuul 1.x 有数量级提升。本文围绕路由、鉴权、限流、熔断、统一响应五个关键设计,给出一套可落地的工程实践。

一、动态路由:配置即代码

网关最核心的职责是请求转发。Spring Cloud Gateway 采用"断言 + 过滤器"模型描述路由,推荐将路由配置外置到 Nacos,实现不重启网关即可调整转发规则。

spring:
  cloud:
    gateway:
      routes:
        - id: user-service
          uri: lb://user-service
          predicates:
            - Path=/api/users/**
          filters:
            - StripPrefix=1
            - name: Retry
              args:
                retries: 3
                statuses: BAD_GATEWAY,GATEWAY_TIMEOUT

lb:// 前缀结合服务发现实现负载均衡;StripPrefix=1 去掉 /api 前缀再转发;Retry 过滤器对网关层超时自动重试,避免上游偶发抖动直接透传给调用方。配合 Nacos 配置中心监听变更,可做到路由热更新。

二、全局过滤器:统一鉴权与上下文传递

业务服务不应重复实现鉴权逻辑。通过 GlobalFilter 在网关层完成 Token 校验,并将解析出的用户身份写入下游请求头,实现一次校验、处处可用。

@Component
public class AuthFilter implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        String token = exchange.getRequest().getHeaders().getFirst("Authorization");
        if (StringUtils.isBlank(token)) {
            return unauthorized(exchange, "缺少认证令牌");
        }
        return jwtVerifier.verify(token)
            .flatMap(claims -> {
                ServerHttpRequest req = exchange.getRequest().mutate()
                    .header("X-User-Id", claims.getSubject())
                    .header("X-Tenant", claims.get("tenant", String.class))
                    .build();
                return chain.filter(exchange.mutate().request(req).build());
            })
            .onErrorResume(e -> unauthorized(exchange, "令牌无效或已过期"));
    }
    @Override
    public int getOrder() { return -100; }
}

getOrder() 返回负值确保该过滤器在路由转发前执行。鉴权通过后以 mutate() 构造新请求注入身份头,下游服务直接读取即可,无需再次解析 JWT。

三、令牌桶限流:保护脆弱上游

突发流量可能压垮下游。Spring Cloud Gateway 内置 RequestRateLimiter 过滤器,基于 Redis 令牌桶算法实现分布式限流。

@Bean
public KeyResolver userKeyResolver() {
    return exchange -> Mono.just(
        exchange.getRequest().getHeaders().getFirst("X-User-Id")
    );
}
filters:
  - name: RequestRateLimiter
    args:
      redis-rate-limiter.replenishRate: 20
      redis-rate-limiter.burstCapacity: 40
      key-resolver: "#{@userKeyResolver}"

replenishRate 为每秒令牌填充数,burstCapacity 为桶容量。按用户维度限流,既防止单用户滥用,又避免全局阈值误伤正常业务。被限流时网关返回 429,前端可据此展示友好提示而非白屏。

四、熔断降级:快速失败优于级联等待

当下游服务不可用时,网关若同步等待超时,会快速耗尽自身线程池引发雪崩。集成 Resilience4j 熔断器,在错误率超阈值时直接走降级逻辑。

filters:
  - name: CircuitBreaker
    args:
      name: userCircuit
      fallbackUri: forward:/fallback/users
@RestController
@RequestMapping("/fallback")
public class FallbackController {
    @GetMapping("/users")
    public Mono<Map<String, Object>> usersFallback() {
        return Mono.just(Map.of(
            "code", 503, "message", "用户服务暂不可用,请稍后重试"
        ));
    }
}

熔断打开后请求被重定向到 fallbackUri,返回兜底数据而非异常。配合 Actuator 暴露的 /actuator/circuitbreakers 端点,可实时观测各熔断器状态,为容量规划提供数据支撑。

五、统一响应与全局异常处理

不同服务返回结构各异,前端需适配多种格式,维护成本高。在网关层用 modifyResponseBody 统一包装,并对异常统一编码。

@Component
public class ResponseWrapperFilter implements GlobalFilter {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        return chain.filter(exchange).then(Mono.fromRunnable(() -> {
            ServerHttpResponse resp = exchange.getResponse();
            if (resp.getStatusCode().is2xxSuccessful()) {
                // 统一为 {code, data, message} 结构
            }
        }));
    }
}

至此,客户端只需对接一套响应协议,后端服务各自演进互不影响。

结语

API 网关是微服务治理的集大成者:路由解决"去哪",鉴权解决"谁能进",限流与熔断解决"扛得住",统一响应解决"好对接"。五个设计环环相扣,共同把横切关注点从业务服务中剥离,让业务代码回归纯粹。实践中建议为网关单独建立监控大盘,关注 P99 延迟、熔断状态与限流命中率三项核心指标,方能真正驾驭这套统一入口。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。