Spring Cloud Gateway网关实战:动态路由与请求限流配置

微服务架构API网关承担统一入口职责,路由转发、鉴权、限流、熔断等横切逻辑从各服务收敛到网关层。Spring Cloud Gateway基于Spring WebFlux构建,非阻塞模型吞吐表现优于Zuul等同步网关。本文给出Gateway的路由配置、动态路由加载、限流与自定义过滤器实现。

Spring Cloud Gateway路由基础配置

Gateway的核心概念是Route(路由)、Predicate(断言)和Filter(过滤器)。一条Route由ID、目标URI、断言链和过滤器链组成。断言决定请求是否匹配该路由,过滤器对请求和响应做加工。

server:
  port: 8080

spring:
  cloud:
    gateway:
      routes:
        - id: user-service
          uri: lb://user-service
          predicates:
            - Path=/api/users/**
            - Method=GET,POST
            - Header=Authorization, .+
          filters:
            - StripPrefix=2
            - AddRequestHeader=X-Gateway-Source, gateway
        - id: order-service
          uri: lb://order-service
          predicates:
            - Path=/api/orders/**
          filters:
            - StripPrefix=2
            - name: RequestRateLimiter
              args:
                redis-rate-limiter.replenishRate: 100
                redis-rate-limiter.burstCapacity: 200

lb://前缀表示使用服务发现(Nacos或Eureka)做负载均衡。StripPrefix=2截掉URL前两层路径,/api/users/detail转发到user-service的/detail。RequestRateLimiter配合Redis实现令牌桶限流,replenishRate为每秒令牌填充速率,burstCapacity为桶容量上限。

动态路由:不重启网关更新路由规则

静态配置每次改路由都要重启网关,生产环境不可接受。动态路由方案把路由定义存入Nacos配置中心,网关监听配置变更实时刷新:

@Configuration
public class DynamicRouteConfig {

    @Autowired
    private RouteDefinitionLocator routeDefinitionLocator;

    @Autowired
    private RouteDefinitionWriter routeDefinitionWriter;

    @Bean
    public ApplicationListener<RefreshRoutesEvent> routesRefreshListener() {
        return event -> {
            // Nacos配置变更时重新加载路由
            routeDefinitionLocator.getRouteDefinitions()
                .collectList()
                .subscribe(definitions -> {
                    // 先清空旧路由
                    definitions.forEach(def ->
                        routeDefinitionWriter.delete(Mono.just(def.getId())));
                    // 写入新路由
                    definitions.forEach(def ->
                        routeDefinitionWriter.save(Mono.just(def)));
                });
        };
    }
}

也可以用Gateway提供的Actuator端点动态增删路由,POST到/actuator/gateway/routes/{id}添加路由,DELETE删除路由,不需要重新打包部署。动态路由配合Nacos配置中心实现路由规则版本化管理,每次变更可追溯。

全局过滤器:鉴权与请求日志

全局过滤器对所有路由生效,适合做鉴权、日志、链路追踪等通用逻辑:

@Component
@Order(-100)
public class AuthGlobalFilter implements GlobalFilter {

    @Autowired
    private JwtUtil jwtUtil;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        String path = request.getURI().getPath();

        // 白名单路径直接放行
        if (path.contains("/auth/login") || path.contains("/auth/register")) {
            return chain.filter(exchange);
        }

        String token = request.getHeaders().getFirst("Authorization");
        if (token == null || !token.startsWith("Bearer ")) {
            return unauthorizedResponse(exchange, "缺少认证令牌");
        }

        try {
            String jwt = token.substring(7);
            Claims claims = jwtUtil.parseToken(jwt);
            // 将用户信息透传到下游服务
            ServerHttpRequest mutated = request.mutate()
                .header("X-User-Id", claims.getSubject())
                .header("X-User-Role", claims.get("role", String.class))
                .build();
            return chain.filter(exchange.mutate().request(mutated).build());
        } catch (Exception e) {
            return unauthorizedResponse(exchange, "令牌无效或已过期");
        }
    }

    private Mono<Void> unauthorizedResponse(ServerWebExchange exchange, String msg) {
        ServerHttpResponse response = exchange.getResponse();
        response.setStatusCode(HttpStatus.UNAUTHORIZED);
        response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
        String body = "{\"code\":401,\"message\":\"" + msg + "\"}";
        DataBuffer buffer = response.bufferFactory()
            .wrap(body.getBytes(StandardCharsets.UTF_8));
        return response.writeWith(Mono.just(buffer));
    }
}

鉴权过滤器在路由过滤器之前执行(@Order(-100)),验证JWT后将用户ID和角色透传到下游服务的请求头中。下游服务从Header中取用户信息,不需要重复验签。

熔断降级与重试策略

Gateway集成Resilience4j实现熔断降级,下游服务异常时返回兜底响应:

spring:
  cloud:
    gateway:
      routes:
        - id: order-service
          uri: lb://order-service
          predicates:
            - Path=/api/orders/**
          filters:
            - name: CircuitBreaker
              args:
                name: orderCircuitBreaker
                fallbackUri: forward:/fallback/order

resilience4j:
  circuitbreaker:
    instances:
      orderCircuitBreaker:
        slidingWindowSize: 10
        failureRateThreshold: 50
        waitDurationInOpenState: 10s
        permittedNumberOfCallsInHalfOpenState: 3

失败率达到50%时熔断器打开,后续请求直接走fallbackUri返回降级响应。10秒后进入半开状态,放行3个探测请求,全部成功则恢复,否则继续熔断。配合Retry过滤器对可重试异常(如超时)做自动重试,但幂等性要求高的接口要限制重试次数,避免重复扣款。

原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/springcloudgateway-wang-guan-shi-zhan-dong-tai-lu-you-yu/

(0)
小编小编
上一篇 1小时前
下一篇 1小时前

相关推荐