Spring Cloud Gateway 是基于 Spring WebFlux 的响应式微服务网关,核心能力:路由转发、断言匹配、过滤器链、限流、鉴权、灰度等。以下从基础搭建、核心配置、高级功能提供完整可运行示例。

一、环境准备与项目搭建

1. 版本选择(推荐稳定组合)

  • Spring Boot:3.2.x
  • Spring Cloud:2023.0.x(Leyton)
  • JDK:17+
  • 注册中心:Nacos 2.x(用于服务发现)

2. 核心依赖(Maven pom.xml)

xml

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>3.2.4</version>
</parent>

<dependencies>
    <!-- Gateway 核心依赖(自动集成 WebFlux,禁止引入 spring-boot-starter-web) -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-gateway</artifactId>
    </dependency>
    <!-- Nacos 服务发现(实现 lb:// 负载均衡路由) -->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        <version>2023.0.1.0</version>
    </dependency>
    <!-- 负载均衡依赖(服务名路由必须) -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-loadbalancer</artifactId>
    </dependency>
    <!-- Redis 限流依赖(可选) -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
    </dependency>
</dependencies>

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>2023.0.1</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

3. 启动类(无额外注解,自动配置)

java

运行

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@SpringBootApplication
@EnableDiscoveryClient // 启用 Nacos 服务发现
public class GatewayApplication {
    public static void main(String[] args) {
        SpringApplication.run(GatewayApplication.class, args);
    }
}

二、基础路由配置(application.yml)

1. 静态路由(直接转发到固定地址)

yaml

server:
  port: 9999 # 网关端口
spring:
  application:
    name: gateway-demo
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848 # Nacos 地址
    gateway:
      routes:
        - id: static-route # 路由唯一ID(不可重复)
          uri: http://httpbin.org # 目标地址(静态)
          predicates: # 断言(匹配条件)
            - Path=/get/** # 路径匹配 /get/** 时转发
          filters: # 过滤器(请求/响应处理)
            - AddRequestHeader=X-Gateway, SpringCloudGateway # 添加请求头
            - RewritePath=/get/(?<segment>.*), /$\{segment} # 路径重写:/get/hello → /hello

2. 服务发现路由(lb:// 负载均衡)

yaml

spring:
  cloud:
    gateway:
      routes:
        - id: user-service-route
          uri: lb://user-service # lb:// + 服务名(Nacos 中注册的服务)
          predicates:
            - Path=/api/user/**
          filters:
            - StripPrefix=1 # 去掉路径前缀:/api/user/1 → /1(转发到 user-service)
            - AddResponseHeader=X-Response-From, Gateway # 添加响应头
      # 自动服务发现路由(开启后,可直接通过 /服务名/** 访问)
      discovery:
        locator:
          enabled: true # 开启自动路由
          lower-case-service-id: true # 服务名小写

三、常用断言与过滤器示例

1. 常用断言(Predicates)

yaml

spring:
  cloud:
    gateway:
      routes:
        - id: predicate-demo
          uri: lb://order-service
          predicates:
            - Path=/api/order/** # 路径匹配
            - Method=GET,POST # 请求方法匹配
            - Header=X-Request-Id, \d+ # 请求头匹配(正则)
            - Query=token, .+ # 请求参数匹配
            - After=2026-01-01T00:00:00+08:00 # 时间之后生效
            - Before=2026-12-31T23:59:59+08:00 # 时间之前生效
            - Between=2026-01-01T00:00:00+08:00,2026-12-31T23:59:59+08:00 # 时间区间

2. 常用过滤器(Filters)

yaml

spring:
  cloud:
    gateway:
      routes:
        - id: filter-demo
          uri: lb://product-service
          predicates:
            - Path=/api/product/**
          filters:
            - StripPrefix=1 # 去掉1级前缀
            - AddRequestHeader=X-User-Id, 1001 # 添加请求头
            - AddRequestParameter=source, gateway # 添加请求参数
            - AddResponseHeader=X-Result, Success # 添加响应头
            - SetStatus=404 # 设置响应状态码
            - RewritePath=/api/product/(?<id>.*), /product/$\{id} # 路径重写

四、高级功能实战

1. 全局过滤器(统一鉴权)

场景:所有请求必须携带 Token,否则返回 401。

java

运行

import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

@Component
public class AuthGlobalFilter implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 1. 获取请求头 Token
        String token = exchange.getRequest().getHeaders().getFirst("Authorization");
        // 2. 校验 Token(实际对接认证服务/Redis)
        if (token == null || !token.startsWith("Bearer ")) {
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
            return exchange.getResponse().setComplete();
        }
        // 3. Token 有效,继续转发
        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return Ordered.HIGHEST_PRECEDENCE; // 最高优先级(最先执行)
    }
}

2. Redis 限流(令牌桶算法)

配置(application.yml)

yaml

spring:
  redis:
    host: 127.0.0.1
    port: 6379
  cloud:
    gateway:
      routes:
        - id: rate-limit-route
          uri: lb://pay-service
          predicates:
            - Path=/api/pay/**
          filters:
            - StripPrefix=1
            - name: RequestRateLimiter # 限流过滤器
              args:
                redis-rate-limiter.replenishRate: 10 # 每秒生成10个令牌
                redis-rate-limiter.burstCapacity: 20 # 最大令牌数(突发流量)
                key-resolver: "#{@ipKeyResolver}" # 限流维度(IP/用户ID)

限流维度配置(IP 限流)

java

运行

import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import reactor.core.publisher.Mono;

@Configuration
public class RateLimitConfig {
    // IP 限流(按客户端 IP 限流)
    @Bean
    public KeyResolver ipKeyResolver() {
        return exchange -> Mono.just(
                exchange.getRequest().getRemoteAddress().getAddress().getHostAddress()
        );
    }

    // 用户ID 限流(可选,从请求头/参数获取)
    @Bean
    public KeyResolver userIdKeyResolver() {
        return exchange -> Mono.just(
                exchange.getRequest().getHeaders().getFirst("X-User-Id")
        );
    }
}

3. 自定义路由断言(灰度发布)

场景:根据请求头 X-Gray-Tag=beta 转发到灰度服务。

java

运行

import org.springframework.cloud.gateway.handler.predicate.AbstractRoutePredicateFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;

@Component
public class GrayRoutePredicateFactory extends AbstractRoutePredicateFactory<GrayRoutePredicateFactory.Config> {

    public GrayRoutePredicateFactory() {
        super(Config.class);
    }

    @Override
    public Predicate<ServerWebExchange> apply(Config config) {
        return exchange -> {
            String grayTag = exchange.getRequest().getHeaders().getFirst("X-Gray-Tag");
            return config.getTag().equals(grayTag);
        };
    }

    @Override
    public List<String> shortcutFieldOrder() {
        return Arrays.asList("tag"); // 配置参数名
    }

    // 配置类
    public static class Config {
        private String tag;
        public String getTag() { return tag; }
        public void setTag(String tag) { this.tag = tag; }
    }
}

灰度路由配置

yaml

spring:
  cloud:
    gateway:
      routes:
        # 灰度路由:X-Gray-Tag=beta → 转发到 beta 服务
        - id: order-gray-route
          uri: lb://order-service-beta
          predicates:
            - Path=/api/order/**
            - Gray=beta # 自定义断言
          filters:
            - StripPrefix=1
        # 普通路由:其他请求 → 转发到正式服务
        - id: order-normal-route
          uri: lb://order-service
          predicates:
            - Path=/api/order/**
          filters:
            - StripPrefix=1

4. 全链路日志过滤器

java

运行

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

@Component
public class LoggingGlobalFilter implements GlobalFilter, Ordered {
    private static final Logger log = LoggerFactory.getLogger(LoggingGlobalFilter.class);

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 记录请求日志
        log.info("Request: {} {} from {}",
                exchange.getRequest().getMethod(),
                exchange.getRequest().getPath(),
                exchange.getRequest().getRemoteAddress());
        // 记录响应日志
        return chain.filter(exchange).doOnSuccess(v ->
                log.info("Response: {} for {}",
                        exchange.getResponse().getStatusCode(),
                        exchange.getRequest().getPath())
        );
    }

    @Override
    public int getOrder() {
        return -1; // 早于鉴权过滤器
    }
}

五、测试与验证

1. 启动服务

  • 启动 Nacos(端口 8848)
  • 启动 user-service、order-service 等微服务(注册到 Nacos)
  • 启动 Gateway 服务(端口 9999)

2. 测试请求

bash

运行

# 测试静态路由
curl http://localhost:9999/get/headers

# 测试服务发现路由
curl http://localhost:9999/api/user/1001

# 测试鉴权(无 Token → 401)
curl http://localhost:9999/api/order/1

# 测试鉴权(携带 Token → 成功)
curl -H "Authorization: Bearer test_token" http://localhost:9999/api/order/1

# 测试灰度路由
curl -H "X-Gray-Tag: beta" http://localhost:9999/api/order/1

六、生产环境建议

  1. 高可用:部署多个 Gateway 实例,前端用 Nginx 负载均衡
  2. 监控:集成 Prometheus + Grafana 监控网关指标
  3. 熔断:集成 Sentinel 实现服务熔断降级
  4. 安全:开启 HTTPS、请求参数校验、防 SQL 注入
  5. 日志:集成 ELK 统一日志管理
Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐