Spring Cloud Gateway 从入门到进阶(全指南)

Spring Cloud Gateway 是 Spring Cloud 生态的微服务网关,基于 WebFlux 响应式编程模型,替代了老旧的 Zuul 网关。它的核心价值是:统一入口、路由转发、业务增强(认证授权、限流熔断、日志监控等),是微服务架构中不可或缺的中间件。

本文从「入门配置→核心功能→进阶实战→性能优化」逐步递进,结合实际项目场景,帮你快速掌握 Gateway 的使用。

一、入门:环境搭建与基础路由(10 分钟上手)

1. 核心依赖(Spring Cloud Alibaba 环境)

在微服务网关模块(如 gateway-server)的 pom.xml 中添加依赖(无需额外引入 Spring MVC,Gateway 基于 WebFlux):

<!-- Gateway 核心依赖 -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!-- Nacos 服务发现(网关需要从注册中心获取服务列表) -->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- Nacos 配置中心(动态路由用) -->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>

2. 基础配置(application.yml)

网关的核心是「路由规则」,入门阶段先配置静态路由和服务发现路由:

spring:
  application:
    name: gateway-server # 网关服务名(Nacos 注册用)
  cloud:
    # Nacos 服务发现配置
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848 # 你的 Nacos 地址
    # Gateway 核心配置
    gateway:
      # 路由规则(可配置多个 route)
      routes:
        # 1. 静态路由:直接指定目标地址(适合非微服务接口,如第三方 API)
        - id: static-route # 路由唯一ID(自定义,不重复)
          uri: http://www.baidu.com # 目标地址(静态地址)
          predicates: # 路由断言(满足条件才转发)
            - Path=/baidu/** # 当请求路径以 /baidu 开头时触发
          filters: # 路由过滤器(对请求/响应做处理)
            - RewritePath=/baidu/(?<segment>.*), /$\{segment} # 路径重写:/baidu/xxx → /xxx

        # 2. 动态路由:从 Nacos 拉取服务(微服务场景核心)
        - id: order-service-route # 路由ID(建议与服务名一致)
          uri: lb://order-server # 目标服务名(lb=负载均衡,从 Nacos 获取实例)
          predicates:
            - Path=/order/** # 请求路径以 /order 开头 → 转发到 order-server
          filters:
            - StripPrefix=1 # 路径剥离:/order/xxx → /xxx(去掉第一层路径)
      # 启用服务发现(让网关能从 Nacos 感知服务上下线)
      discovery:
        locator:
          enabled: true # 开启服务发现路由(默认关闭)
          lower-case-service-id: true # 服务名转为小写(如 ORDER-SERVER → order-server)
server:
  port: 8080 # 网关端口(公网入口,如 80 端口)

3. 启动网关

创建启动类(无需加 @EnableWebMvc,Gateway 自动配置 WebFlux):

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);
    }
}

4. 测试验证

  • 启动 Nacos、order-server、gateway-server;
  • 访问静态路由:http://localhost:8080/baidu → 跳转到百度;
  • 访问微服务路由:http://localhost:8080/order/xxx → 转发到 order-server 的 /xxx 接口(需确保 order-server 有对应接口)。

二、核心概念:3 个核心组件(必懂)

Gateway 的所有功能都围绕「路由(Route)、断言(Predicate)、过滤器(Filter)」展开,理解这 3 个组件就能掌握 Gateway 的核心逻辑:

组件作用
Route(路由)网关的基本单元,包含「目标地址、断言、过滤器」三部分,是转发规则的最小单位。
Predicate(断言)路由的「触发条件」,判断请求是否满足规则(如路径、方法、请求头、时间等),满足则转发。
Filter(过滤器)路由的「增强逻辑」,对请求(前置处理)或响应(后置处理)做加工(如路径重写、认证、限流)。

1. 常用 Predicate(路由断言)

断言支持多种条件组合,满足条件才触发路由,常用场景:

routes:
  - id: demo-route
    uri: lb://order-server
    predicates:
      # 1. 路径断言(最常用):/order/** 或 /order/123
      - Path=/order/**
      # 2. 方法断言:只允许 GET 请求
      - Method=GET
      # 3. 请求头断言:必须包含 X-Token 请求头
      - Header=X-Token, \d+ # 第二个参数是正则(可选)
      # 4. 参数断言:请求必须包含 id 参数(值为数字)
      - Query=id, \d+
      # 5. 时间断言:在 2025-01-01 到 2025-12-31 之间有效
      - Between=2025-01-01T00:00:00+08:00, 2025-12-31T23:59:59+08:00
      # 6. IP 断言:只允许 192.168.1.0/24 网段访问
      - RemoteAddr=192.168.1.0/24

2. 常用 Filter(路由过滤器)

Gateway 提供两种过滤器:GatewayFilter(路由级,只对当前路由生效) 和 GlobalFilter(全局级,对所有路由生效)

(1)内置 GatewayFilter(直接配置使用)
routes:
  - id: order-service-route
    uri: lb://order-server
    predicates:
      - Path=/order/**
    filters:
      # 1. 路径剥离:去掉第1层路径(/order/xxx → /xxx)
      - StripPrefix=1
      # 2. 路径重写:/order/api/xxx → /api/xxx
      - RewritePath=/order/(?<segment>.*), /$\{segment}
      # 3. 添加请求头:给转发的请求添加 X-Request-Source=gateway
      - AddRequestHeader=X-Request-Source, gateway
      # 4. 添加响应头:给客户端响应添加 X-Response-Time=2025
      - AddResponseHeader=X-Response-Time, 2025
      # 5. 限流:每秒最多100个请求(基于 Redis 实现,需引入 spring-boot-starter-data-redis-reactive)
      - name: RequestRateLimiter
        args:
          redis-rate-limiter.replenishRate: 100 # 令牌桶填充速率(每秒)
          redis-rate-limiter.burstCapacity: 200 # 令牌桶最大容量(峰值)
          key-resolver: "#{@ipKeyResolver}" # 限流键解析器(IP 限流)
(2)自定义 GlobalFilter(全局生效,如认证授权)

全局过滤器适合做「统一认证、日志采集、链路追踪」等全局逻辑,示例:统一 Token 校验(未带 Token 直接拦截):

import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

@Configuration
public class GlobalAuthFilterConfig {

    /**
     * 自定义全局认证过滤器(Order 越小,执行优先级越高)
     */
    @Bean
    @Order(-100) // 优先级高于默认过滤器(默认 0)
    public GlobalFilter authFilter() {
        return (exchange, chain) -> {
            // 1. 获取请求头中的 Token
            String token = exchange.getRequest().getHeaders().getFirst("X-Token");
            
            // 2. 校验 Token(实际场景:对接 Redis/鉴权服务校验)
            if (token == null || token.isEmpty()) {
                // 3. Token 无效:返回 401 未授权
                exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
                return exchange.getResponse().setComplete();
            }
            
            // 4. Token 有效:继续转发请求到下游服务
            return chain.filter(exchange);
        };
    }

    /**
     * 自定义限流键解析器(IP 限流)
     */
    @Bean
    public KeyResolver ipKeyResolver() {
        return exchange -> Mono.just(
            // 获取客户端 IP 地址作为限流键
            exchange.getRequest().getRemoteAddress().getAddress().getHostAddress()
        );
    }
}

三、进阶:核心功能实战(微服务必备)

1. 动态路由(基于 Nacos 配置中心)

静态路由需要重启网关才能更新,动态路由通过 Nacos 配置中心实现「配置推送即生效」,步骤如下:

(1)Nacos 中创建网关配置

在 Nacos 控制台新建配置:

  • Data ID:gateway-server.yaml(与网关服务名一致)
  • Group:DEFAULT_GROUP
  • 配置内容(路由规则动态更新):
spring:
  cloud:
    gateway:
      routes:
        - id: order-service-route
          uri: lb://order-server
          predicates:
            - Path=/order/**
          filters:
            - StripPrefix=1
        # 新增/修改路由直接在这里操作,无需重启网关
        - id: stock-service-route
          uri: lb://stock-server
          predicates:
            - Path=/stock/**
          filters:
            - StripPrefix=1
(2)网关启用 Nacos 动态配置

在网关的 bootstrap.yml 中配置 Nacos 配置中心(优先级高于 application.yml):

spring:
  cloud:
    nacos:
      config:
        server-addr: 127.0.0.1:8848 # Nacos 地址
        file-extension: yaml # 配置文件格式
        group: DEFAULT_GROUP # 配置分组
  application:
    name: gateway-server # 对应 Nacos 的 Data ID 前缀
(3)测试动态路由
  • 修改 Nacos 中 gateway-server.yaml 的路由规则(如新增一个路由);
  • 无需重启网关,直接访问新路由(如 /stock/xxx),即可生效。

2. 整合 Sentinel 限流熔断(流量防护)

Gateway 与 Sentinel 无缝集成,实现「网关层限流」(避免下游服务被压垮),步骤如下:

(1)添加依赖
<!-- Sentinel 网关适配依赖 -->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
</dependency>
<!-- Sentinel 核心依赖(已引入可忽略) -->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
(2)配置 Sentinel 控制台

在 application.yml 中添加:

spring:
  cloud:
    sentinel:
      transport:
        dashboard: 127.0.0.1:8080 # Sentinel 控制台地址
        port: 8719 # 客户端与控制台通信端口
      # 启用网关限流规则(默认关闭)
      filter:
        enabled: true
(3)在 Sentinel 控制台配置网关限流
  1. 启动 Sentinel 控制台(java -jar sentinel-dashboard-1.8.6.jar);
  2. 启动网关和下游服务,访问网关接口(触发 Sentinel 初始化);
  3. Sentinel 控制台 → 网关路由限流 → 新增规则:
  • 资源名:路由 ID(如 order-service-route);
  • 限流阈值:10(每秒最多 10 个请求);
  • 统计周期:1 秒;
  1. 压测测试:快速访问 /order/xxx,超过阈值会返回 Blocked by Sentinel: FlowException

3. 灰度发布(基于请求头 / 参数路由)

灰度发布是微服务的核心需求(让部分用户体验新功能),Gateway 可通过「自定义路由断言」实现:

示例:按请求头 X-Gray-Tag=beta 路由到新版本服务
import org.springframework.cloud.gateway.handler.predicate.AbstractRoutePredicateFactory;
import org.springframework.cloud.gateway.handler.predicate.GatewayPredicate;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;

import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;

// 自定义路由断言工厂(命名规则:XXXRoutePredicateFactory)
@Component
public class GrayRoutePredicateFactory extends AbstractRoutePredicateFactory<GrayRoutePredicateFactory.Config> {

    // 配置类:存储断言参数(如灰度标签)
    public static class Config {
        private String tag; // 灰度标签(如 beta)

        public String getTag() { return tag; }
        public void setTag(String tag) { this.tag = tag; }
    }

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

    // 构建断言逻辑:请求头包含 X-Gray-Tag=配置的 tag 则生效
    @Override
    public Predicate<ServerWebExchange> apply(Config config) {
        return exchange -> {
            String grayTag = exchange.getRequest().getHeaders().getFirst("X-Gray-Tag");
            return config.getTag().equals(grayTag);
        };
    }

    // 配置参数名称(用于 yaml 配置)
    @Override
    public List<String> shortcutFieldOrder() {
        return Arrays.asList("tag");
    }
}
配置灰度路由
spring:
  cloud:
    gateway:
      routes:
        # 灰度路由:X-Gray-Tag=beta → 转发到 order-server-beta(新版本服务)
        - id: order-service-gray
          uri: lb://order-server-beta
          predicates:
            - Path=/order/**
            - Gray=beta # 自定义断言(对应上面的 GrayRoutePredicateFactory)
          filters:
            - StripPrefix=1
        # 普通路由:其他请求 → 转发到 order-server(旧版本服务)
        - id: order-service-normal
          uri: lb://order-server
          predicates:
            - Path=/order/**
          filters:
            - StripPrefix=1
测试灰度发布
  • 给请求添加头 X-Gray-Tag=beta → 访问新版本服务;
  • 无该请求头 → 访问旧版本服务。

4. 分布式链路追踪(整合 SkyWalking)

网关作为请求入口,需要接入链路追踪,确保「请求→网关→服务 1→服务 2」的链路可追溯:

(1)添加依赖
<!-- SkyWalking 网关适配依赖 -->
<dependency>
    <groupId>org.apache.skywalking</groupId>
    <artifactId>apm-spring-cloud-gateway-3.x-plugin</artifactId>
    <version>8.16.0</version> <!-- 与 SkyWalking 服务端版本一致 -->
</dependency>
<!-- SkyWalking 核心依赖(已引入可忽略) -->
<dependency>
    <groupId>org.apache.skywalking</groupId>
    <artifactId>apm-toolkit-trace</artifactId>
    <version>8.16.0</version>
</dependency>
(2)配置 SkyWalking 代理

启动网关时,添加 JVM 参数(指定 SkyWalking 服务端地址):

-javaagent:D:\skywalking-agent\skywalking-agent.jar
-Dskywalking.agent.service_name=gateway-server
-Dskywalking.collector.backend_service=127.0.0.1:11800
(3)查看链路追踪

启动 SkyWalking 服务端,访问网关接口后,在 SkyWalking 控制台 → 链路追踪,可看到完整的请求链路(网关→下游服务)。

四、高阶:性能优化与生产实践

1. 性能优化技巧

Gateway 基于 WebFlux(响应式),性能优于传统 MVC,但需注意以下优化点:

(1)关闭 Netty 日志(减少 IO 开销)

在 logback.xml 中添加:

<logger name="reactor.netty" level="WARN" />
<logger name="io.netty" level="WARN" />
(2)调整 Netty 线程池(适配 CPU 核心数)
spring:
  cloud:
    gateway:
      httpclient:
        reactor:
          # 工作线程数(默认 CPU 核心数 * 2)
          workerGroupThreads: 16
          # 事件循环线程数(默认 CPU 核心数)
          eventLoopGroupThreads: 4
(3)启用连接池复用
spring:
  cloud:
    gateway:
      httpclient:
        pool:
          max-idle-time: 60000 # 连接最大空闲时间(60秒)
          max-life-time: 120000 # 连接最大生命周期(120秒)
          max-connections: 1000 # 最大连接数(根据并发量调整)
(4)禁用不必要的过滤器

避免全局过滤器做过多耗时操作(如复杂计算、数据库查询),必要时用异步处理。

2. 生产环境必备配置

(1)高可用部署(多实例 + Nginx 负载均衡)

网关是入口,必须集群部署,避免单点故障:

用户 → Nginx(边缘网关) → 多个 Gateway 实例 → 微服务

Nginx 配置示例(转发到网关集群):

upstream gateway_cluster {
    server 192.168.1.100:8080;
    server 192.168.1.101:8080;
}

server {
    listen 80;
    server_name api.yourdomain.com;

    location / {
        proxy_pass http://gateway_cluster;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}
(2)超时配置(避免请求阻塞)
spring:
  cloud:
    gateway:
      httpclient:
        connect-timeout: 5000 # 连接超时(5秒)
        response-timeout: 10000 # 响应超时(10秒)
      routes:
        - id: order-service-route
          uri: lb://order-server
          predicates:
            - Path=/order/**
          filters:
            - StripPrefix=1
            - name: RequestTimeFilter
              args:
                responseTimeOut: 10000 # 路由级超时(覆盖全局)
(3)跨域配置(解决前端跨域问题)
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.reactive.CorsWebFilter;
import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;

@Configuration
public class CorsConfig {

    @Bean
    public CorsWebFilter corsWebFilter() {
        CorsConfiguration config = new CorsConfiguration();
        config.addAllowedOrigin("*"); // 允许所有源(生产环境指定具体域名,如 https://xxx.com)
        config.addAllowedMethod("*"); // 允许所有请求方法(GET/POST/PUT/DELETE)
        config.addAllowedHeader("*"); // 允许所有请求头
        config.setAllowCredentials(true); // 允许携带 Cookie

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", config); // 对所有路径生效

        return new CorsWebFilter(source);
    }
}

3. 常见问题排查

(1)路由不生效
  • 检查路由 ID 是否重复;
  • 断言条件是否满足(如路径是否匹配、请求头是否存在);
  • 服务发现是否启用(discovery.locator.enabled=true);
  • 下游服务是否已注册到 Nacos(网关日志中查看 Loaded service instances for service xxx)。
(2)请求超时
  • 检查网关与下游服务的网络连通性;
  • 调整 connect-timeout 和 response-timeout 配置;
  • 排查下游服务是否响应缓慢(如数据库查询耗时过长)。
(3)Sentinel 控制台看不到网关路由
  • 确保已引入 spring-cloud-alibaba-sentinel-gateway 依赖;
  • 访问网关接口触发 Sentinel 初始化;
  • 检查 Sentinel 控制台地址配置是否正确。

五、总结

Gateway 是微服务架构的「流量入口网关」,核心优势是:

  1. 原生集成 Spring 生态(Nacos、Sentinel、SkyWalking),开发成本低;
  2. 基于 WebFlux 响应式,性能优异;
  3. 支持动态路由、灰度发布、限流熔断等微服务核心需求。

学习路径建议:

  1. 入门:掌握基础路由、服务发现、内置过滤器;
  2. 进阶:实现动态路由、Sentinel 限流、灰度发布;
  3. 生产:优化性能、高可用部署、问题排查。

实际项目中,Gateway 通常与 Nginx 配合使用(Nginx 负责边缘网关,Gateway 负责微服务网关),各司其职,打造稳定、高效的微服务入口。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

canjun_wen

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值