Skip to content
清晨的一缕阳光
返回

Spring Cloud Gateway 核心

Spring Cloud Gateway 核心

Spring Cloud Gateway 简介

Spring Cloud Gateway 是 Spring Cloud 官方推出的网关解决方案,基于 Spring WebFlux 构建,提供路由转发、过滤器、限流等功能。

核心概念

工作原理

┌─────────────┐
│   Client    │
└──────┬──────┘


┌─────────────────────────────────────────┐
│         Spring Cloud Gateway            │
│                                         │
│  ┌─────────────────────────────────┐   │
│  │        Handler Mapping          │   │
│  │    (Route Predicate Router)     │   │
│  └──────────────┬──────────────────┘   │
│                 │                       │
│  ┌──────────────▼──────────────────┐   │
│  │      Web Filter Chain           │   │
│  │  ┌─────────┐  ┌─────────┐      │   │
│  │  │ Filter  │  │ Filter  │ ...  │   │
│  │  │   Pre   │  │  Post   │      │   │
│  │  └─────────┘  └─────────┘      │   │
│  └──────────────┬──────────────────┘   │
│                 │                       │
│  ┌──────────────▼──────────────────┐   │
│  │        Proxy Handler            │   │
│  └──────────────┬──────────────────┘   │
└─────────────────┼───────────────────────┘


         ┌────────────────┐
         │  Microservices │
         └────────────────┘

核心优势

快速开始

1. 添加依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

2. 配置路由

spring:
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true  # 启用服务发现
          lower-case-service-id: true  # 服务名转小写
      routes:
        - id: user-service
          uri: lb://user-service
          predicates:
            - Path=/api/users/**
          filters:
            - StripPrefix=1
            - AddRequestHeader=X-Request-Source, gateway
        - id: order-service
          uri: lb://order-service
          predicates:
            - Path=/api/orders/**
          filters:
            - StripPrefix=1

3. 启动类

@SpringBootApplication
@EnableDiscoveryClient
public class GatewayApplication {
    public static void main(String[] args) {
        SpringApplication.run(GatewayApplication.class, args);
    }
}

路由配置

断言工厂

1. Path 断言

predicates:
  - Path=/api/users/**
  - Path=/api/orders/{id}

2. Method 断言

predicates:
  - Method=GET,POST

3. Header 断言

predicates:
  - Header=X-Request-Id, \d+

4. Query 断言

predicates:
  - Query=page, \d+
  - Query=keyword, .+
predicates:
  - Cookie=sessionId, .+

6. Host 断言

predicates:
  - Host=**.example.com

7. Between 断言

predicates:
  - Between=2026-01-01T00:00:00.000Z[Asia/Shanghai], 2026-12-31T23:59:59.999Z[Asia/Shanghai]

8. Before/After 断言

predicates:
  - Before=2026-06-01T00:00:00.000Z[Asia/Shanghai]
  - After=2026-01-01T00:00:00.000Z[Asia/Shanghai]

9. Weight 断言(权重)

predicates:
  - Weight=group1, 80  # 80% 流量

组合断言

predicates:
  - Path=/api/users/**
  - Method=GET,POST
  - Header=X-Request-Id, \d+

过滤器

内置过滤器

1. StripPrefix

filters:
  - StripPrefix=1  # 去掉路径的第一部分

2. AddRequestHeader

filters:
  - AddRequestHeader=X-Request-Source, gateway

3. AddResponseHeader

filters:
  - AddResponseHeader=X-Response-Time, 2026-04-10

4. SetRequestHeader

filters:
  - SetRequestHeader=Host, new-host

5. RemoveRequestHeader

filters:
  - RemoveRequestHeader=Cookie

6. RewritePath

filters:
  - RewritePath=/api/(?<segment>.*), /$\{segment}

7. RedirectTo

filters:
  - RedirectTo=302, http://example.com

8. CircuitBreaker

filters:
  - name: CircuitBreaker
    args:
      name: myCircuitBreaker
      fallbackUri: forward:/fallback

9. RequestRateLimiter

filters:
  - name: RequestRateLimiter
    args:
      redis-rate-limiter.replenishRate: 10
      redis-rate-limiter.burstCapacity: 20

自定义过滤器

全局过滤器

@Component
public class GlobalAuthFilter implements GlobalFilter, Ordered {
    
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        
        // 获取认证信息
        String token = request.getHeaders().getFirst("Authorization");
        
        // 验证 Token
        if (!validateToken(token)) {
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
            return exchange.getResponse().setComplete();
        }
        
        // 添加用户信息到请求头
        ServerHttpRequest mutatedRequest = request.mutate()
            .header("X-User-ID", getUserIdFromToken(token))
            .build();
        
        return chain.filter(exchange.mutate().request(mutatedRequest).build());
    }
    
    @Override
    public int getOrder() {
        return -100;  // 优先级
    }
    
    private boolean validateToken(String token) {
        // Token 验证逻辑
        return token != null && token.startsWith("Bearer ");
    }
    
    private String getUserIdFromToken(String token) {
        // 从 Token 中提取用户 ID
        return "user123";
    }
}

局部过滤器工厂

@Component
public class CustomFilterFactory extends AbstractGatewayFilterFactory<CustomFilterFactory.Config> {
    
    public CustomFilterFactory() {
        super(Config.class);
    }
    
    @Override
    public GatewayFilter apply(Config config) {
        return (exchange, chain) -> {
            ServerHttpRequest request = exchange.getRequest();
            
            // 前置处理
            log.info("执行自定义过滤器:{}", config.getName());
            
            return chain.filter(exchange)
                .then(Mono.fromRunnable(() -> {
                    // 后置处理
                    log.info("响应状态码:{}", exchange.getResponse().getStatusCode());
                }));
        };
    }
    
    public static class Config {
        private String name;
        
        // getter/setter
    }
}

使用:

filters:
  - CustomFilter=name

负载均衡

集成 Spring Cloud LoadBalancer

spring:
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true
      httpclient:
        pool:
          type: ELASTIC
          max-connections: 100
          max-connections-per-route: 20

负载均衡策略

@Configuration
public class LoadBalancerConfig {
    
    @Bean
    @LoadBalanced
    public WebClient.Builder loadBalancedWebClientBuilder() {
        return WebClient.builder();
    }
    
    @Bean
    public ReactorLoadBalancer<ServiceInstance> loadBalancer(
        Environment environment,
        LoadBalancerClientFactory loadBalancerClientFactory
    ) {
        String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);
        return loadBalancerClientFactory.getInstance(name);
    }
}

跨域配置

@Configuration
public class CorsConfig {
    
    @Bean
    public CorsWebFilter corsWebFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();
        
        config.addAllowedOriginPattern("*");
        config.addAllowedHeader("*");
        config.addAllowedMethod("*");
        config.setAllowCredentials(true);
        config.setMaxAge(3600L);
        
        source.registerCorsConfiguration("/**", config);
        
        return new CorsWebFilter(source);
    }
}

监控与指标

集成 Actuator

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
management:
  endpoints:
    web:
      exposure:
        include: health,info,metrics,gateway
  endpoint:
    gateway:
      enabled: true

访问指标

# 查看路由信息
curl http://localhost:8080/actuator/gateway/routes

# 查看全局指标
curl http://localhost:8080/actuator/metrics/gateway.requests

# 查看健康状态
curl http://localhost:8080/actuator/health

高可用部署

1. 多实例部署

server:
  port: 8080  # 不同实例使用不同端口

2. Nginx 负载均衡

upstream gateway {
    server gateway1:8080;
    server gateway2:8080;
    server gateway3:8080;
}

server {
    listen 80;
    server_name api.example.com;
    
    location / {
        proxy_pass http://gateway;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

3. 配置持久化

spring:
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true
      routes:
        - id: user-service
          uri: lb://user-service
          predicates:
            - Path=/api/users/**
          metadata:
            version: 1.0.0

生产实践

1. 统一鉴权

@Component
public class AuthFilter implements GlobalFilter {
    
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        
        // 白名单放行
        if (isWhiteList(request.getPath().value())) {
            return chain.filter(exchange);
        }
        
        // 验证 Token
        String token = extractToken(request);
        if (!validateToken(token)) {
            return unauthorized(exchange);
        }
        
        // 传递用户信息
        return chain.filter(exchange);
    }
    
    private boolean isWhiteList(String path) {
        return path.startsWith("/api/auth/");
    }
    
    private String extractToken(ServerHttpRequest request) {
        String bearerToken = request.getHeaders().getFirst("Authorization");
        if (bearerToken != null && bearerToken.startsWith("Bearer ")) {
            return bearerToken.substring(7);
        }
        return null;
    }
    
    private boolean validateToken(String token) {
        return redisTemplate.hasKey("token:" + token);
    }
    
    private Mono<Void> unauthorized(ServerWebExchange exchange) {
        exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
        return exchange.getResponse().setComplete();
    }
}

2. 限流配置

@Configuration
public class RateLimiterConfig {
    
    @Bean
    public KeyResolver ipKeyResolver() {
        return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getAddress().getHostAddress());
    }
    
    @Bean
    public KeyResolver userKeyResolver() {
        return exchange -> {
            String userId = exchange.getRequest().getHeaders().getFirst("X-User-ID");
            return Mono.just(userId != null ? userId : "anonymous");
        };
    }
}

3. 日志记录

logging:
  level:
    org.springframework.cloud.gateway: DEBUG
    reactor.netty.http.client: DEBUG

常见问题

1. 路由不生效

问题:配置的路由没有生效

排查步骤

2. 跨域问题

问题:前端调用报跨域错误

解决方案

3. 文件上传失败

问题:大文件上传失败

解决方案

spring:
  cloud:
    gateway:
      httpclient:
        max-in-memory-size: 104857600  # 100MB

总结

Spring Cloud Gateway 提供了强大的路由和过滤功能,是微服务架构的理想网关选择。

通过合理配置路由规则和过滤器,可以实现统一鉴权、限流、日志记录等功能。

在生产环境中,建议配置多实例实现高可用,并完善监控和日志记录。


分享这篇文章到:

上一篇文章
MySQL 读写分离实战
下一篇文章
思维链(CoT)工程实践