乐途乐途
主页
  • 计算机基础

    • TCP/IP
    • Linux
    • HTTP
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C
    • C++
    • Java SE
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • Maven 入门
    • Maven 进阶
    • MyBatis
    • Spring
    • Spring MVC
  • Java

    • Spring Boot
    • Spring Cloud
    • Spring Cloud Alibaba
    • Spring Security
    • Spring AI
    • Spring Batch
    • Kafka
    • Java 设计模式
  • 缓存

    • Redis
  • 搜索引擎

    • Elasticsearch
  • 分布式协调

    • ZooKeeper
联系
阿里云
主页
  • 计算机基础

    • TCP/IP
    • Linux
    • HTTP
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C
    • C++
    • Java SE
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • Maven 入门
    • Maven 进阶
    • MyBatis
    • Spring
    • Spring MVC
  • Java

    • Spring Boot
    • Spring Cloud
    • Spring Cloud Alibaba
    • Spring Security
    • Spring AI
    • Spring Batch
    • Kafka
    • Java 设计模式
  • 缓存

    • Redis
  • 搜索引擎

    • Elasticsearch
  • 分布式协调

    • ZooKeeper
联系
阿里云
  • 学习路径
  • Spring Cloud Alibaba概述与技术选型
  • Nacos注册中心
  • Nacos配置中心
  • Sentinel流量控制
  • Sentinel降级与熔断
  • Seata分布式事务
  • RocketMQ消息驱动
  • Spring AI Alibaba与AI集成
  • Dubbo RPC服务调用
  • Gateway服务网关
  • GraalVM静态编译
  • 其他组件速览
  • Alibaba最佳实践与面试考点

Gateway 服务网关

定位说明

Spring Cloud Gateway 是基于 Spring WebFlux 的 API 网关,作为微服务架构的统一入口,承担路由转发、鉴权、限流、日志等横切关注点。Spring Cloud Alibaba 生态中,Gateway 与 Nacos 深度集成,实现动态路由、从注册中心自动发现服务等能力。

与 Netflix Zuul 的区别:Gateway 基于 Reactor 响应式编程(非阻塞 I/O),性能远优于基于 Servlet 的 Zuul 1.x;Zuul 2.x 已停更,Gateway 是 Spring 官方推荐的唯一网关方案。

前置知识:读者应掌握 Spring Boot 基础、Nacos 注册中心。


核心概念速览

Gateway 的核心三要素:

要素说明类比
Route(路由)网关的基本构建块,包含 ID、目标 URI、断言集合、过滤器集合Nginx 的 location
Predicate(断言)匹配 HTTP 请求的条件(路径、Header、参数等)Nginx 的 if 判断
Filter(过滤器)对请求/响应进行修改处理的拦截器Servlet Filter

环境准备

Maven 依赖

<dependencies>
    <!-- Spring Cloud 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>

    <!-- Gateway 集成 Nacos(lb:// 协议支持) -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-loadbalancer</artifactId>
    </dependency>
</dependencies>

注意:Gateway 基于 WebFlux,不能同时引入 spring-boot-starter-web(Servlet 容器),否则启动报错。

基本配置文件

server:
  port: 8080

spring:
  application:
    name: api-gateway
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
    gateway:
      discovery:
        locator:
          enabled: true                # 自动从 Nacos 发现服务并生成路由
          lower-case-service-id: true  # 服务名转为小写
      routes:
        - id: user-service            # 路由 ID,唯一
          uri: lb://user-service      # lb:// 表示从 Nacos 负载均衡获取地址
          predicates:
            - Path=/api/users/**      # 匹配 /api/users/xxx 请求

路由配置详解

一、基础路由方式

Gateway 支持三种路由配置方式:

方式说明灵活性
自动发现路由discovery.locator.enabled=true,自动将 Nacos 中的服务生成路由低,路由规则固定为 /{service-name}/**
YAML 静态配置在 application.yml 中显式定义 routes中,需重启应用
编码动态路由用代码定义 RouteLocator,可从数据库加载高,支持动态更新

二、YAML 静态路由示例

spring:
  cloud:
    gateway:
      routes:
        # 用户服务
        - id: user-service
          uri: lb://user-service
          predicates:
            - Path=/api/users/**
          filters:
            - StripPrefix=1               # 转发前去掉 /api 前缀

        # 订单服务(按时间匹配)
        - id: order-service
          uri: lb://order-service
          predicates:
            - Path=/api/orders/**
            - After=2026-01-01T00:00:00+08:00    # 仅在指定时间后生效
          filters:
            - StripPrefix=1

        # 商品服务(按 Header 匹配)
        - id: product-service
          uri: lb://product-service
          predicates:
            - Path=/api/products/**
            - Header=X-API-Version, 2.0          # 仅匹配特定 Header 的请求
          filters:
            - StripPrefix=1

三、编码动态路由

@Configuration
public class GatewayRouteConfig {

    @Bean
    public RouteLocator customRoutes(RouteLocatorBuilder builder) {
        return builder.routes()
            .route("baidu-route", r -> r
                .path("/baidu/**")
                .uri("https://www.baidu.com"))
            .route("user-route", r -> r
                .path("/api/users/**")
                .filters(f -> f.stripPrefix(1)
                               .addRequestHeader("X-Gateway", "true"))
                .uri("lb://user-service"))
            .build();
    }
}

Predicate(断言)速查

断言工厂说明示例
Path按路径匹配Path=/api/users/**
Method按 HTTP 方法匹配Method=GET,POST
Header按请求头匹配Header=X-Token, .+
Query按查询参数匹配Query=version, v2
Host按 Host 头匹配Host=**.example.com
After在指定时间后匹配After=2026-01-01T00:00:00+08:00
Before在指定时间前匹配Before=2027-01-01T00:00:00+08:00
Between在指定时间段内匹配Between=...
Cookie按 Cookie 匹配Cookie=sessionId, .+
RemoteAddr按客户端 IP 匹配RemoteAddr=192.168.1.0/24
Weight按权重路由(灰度发布)Weight=group1, 80

Filter(过滤器)速查

内置过滤器

过滤器工厂说明示例
StripPrefix去除路径前缀StripPrefix=1(去掉 1 段)
AddRequestHeader添加请求头AddRequestHeader=X-Source, gateway
AddRequestParameter添加请求参数AddRequestParameter=source, gateway
RemoveRequestHeader移除请求头RemoveRequestHeader=X-Secret
AddResponseHeader添加响应头AddResponseHeader=X-Response-Time, %s
PrefixPath添加路径前缀PrefixPath=/api
RewritePath正则路径重写RewritePath=/api/(?<seg>.*), /$\{seg}
SetStatus设置响应状态码SetStatus=401
Retry重试机制Retry=3

自定义全局过滤器

@Component
@Slf4j
public class RequestLoggingFilter implements GlobalFilter, Ordered {

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

        log.info("[Gateway] {} {}", method, path);

        long start = System.currentTimeMillis();
        return chain.filter(exchange).then(Mono.fromRunnable(() -> {
            long duration = System.currentTimeMillis() - start;
            log.info("[Gateway] {} {} — {}ms",
                    method, path, duration);
        }));
    }

    @Override
    public int getOrder() {
        return -1;  // 最先执行
    }
}

与 Nacos 深度集成

一、动态路由(无需重启)

Gateway 默认将路由配置写在 YAML 中,修改需重启。配合 Nacos Config 可实现动态路由更新:

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
spring:
  cloud:
    nacos:
      config:
        server-addr: 127.0.0.1:8848
        file-extension: yaml
        shared-configs:
          - data-id: gateway-routes.yaml
            group: DEFAULT_GROUP
            refresh: true          # 支持动态刷新

在 Nacos 控制台中修改 gateway-routes.yaml,Gateway 会监听到变更并自动更新路由表。

二、lb:// 协议与服务发现

lb://service-name 是 Gateway 内置的负载均衡协议,底层调用 Spring Cloud LoadBalancer 从 Nacos 获取实例列表并选择。无需手动配置目标 IP:Port。


限流(Rate Limiting)

Gateway 内置基于 Redis + 令牌桶算法 的限流器。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>
@Configuration
public class RateLimitConfig {

    @Bean
    public KeyResolver userKeyResolver() {
        // 按请求路径限流
        return exchange -> Mono.just(
                exchange.getRequest().getURI().getPath());
    }

    @Bean
    public KeyResolver ipKeyResolver() {
        // 按客户端 IP 限流
        return exchange -> {
            String ip = exchange.getRequest().getRemoteAddress()
                    .getAddress().getHostAddress();
            return Mono.just(ip);
        };
    }
}
spring:
  cloud:
    gateway:
      routes:
        - id: user-service
          uri: lb://user-service
          predicates:
            - Path=/api/users/**
          filters:
            - name: RequestRateLimiter
              args:
                redis-rate-limiter.replenishRate: 10     # 每秒允许 10 个请求
                redis-rate-limiter.burstCapacity: 20     # 突发容量 20
                key-resolver: "#{@ipKeyResolver}"        # 按 IP 限流

跨域(CORS)配置

spring:
  cloud:
    gateway:
      globalcors:
        cors-configurations:
          '[/**]':
            allowed-origins: "https://www.example.com"
            allowed-methods: GET, POST, PUT, DELETE
            allowed-headers: "*"
            allow-credentials: true
            max-age: 3600

或用 Java 配置:

@Configuration
public class CorsConfig implements WebFilter {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
        ServerHttpResponse response = exchange.getResponse();
        response.getHeaders().add("Access-Control-Allow-Origin", "*");
        response.getHeaders().add("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");
        response.getHeaders().add("Access-Control-Allow-Headers", "*");
        return chain.filter(exchange);
    }
}

生产实践

一、架构最佳实践

                     ┌──────────────────┐
                     │  Nginx / SLB     │ (公网入口)
                     └────────┬─────────┘
                              │
                     ┌────────▼─────────┐
                     │ Spring Cloud     │ (统一网关层)
                     │ Gateway          │
                     └──┬──────┬──────┬─┘
                        │      │      │
              ┌─────────▼─┐ ┌──▼───┐ ┌▼─────────┐
              │ User Svc  │ │Order │ │Product Svc│ (微服务层)
              └───────────┘ │Svc   │ └───────────┘
                            └──────┘

二、常见问题与解决方案

问题原因解决方案
Gateway 启动报 "No qualifying bean of type 'org.springframework.web.reactive.DispatcherHandler'"同时引入了 spring-boot-starter-web移除 web starter,Gateway 基于 WebFlux
路由不生效Predicate 条件未命中开启 debug 日志:logging.level.org.springframework.cloud.gateway=DEBUG
504 Gateway Timeout后端服务响应超时增大 connect-timeout / response-timeout
大文件上传失败默认 body 大小限制配置 spring.cloud.gateway.routes[].filters[].name=RequestSize

面试考点

1. Gateway 的工作流程?

请求 → Gateway Handler Mapping(匹配路由)→ Web Handler(执行过滤器链)→ 转发到后端服务 → 响应经过滤器链回传。过滤器链按 Ordered 接口排序。

2. Gateway 和 Zuul 的区别?

维度GatewayZuul 1.x
编程模型非阻塞(Reactor/WebFlux)阻塞(Servlet 2.5)
性能高(事件驱动)较低(线程池 + 连接池)
维护状态Spring 官方活跃维护Netflix 停更
长连接支持WebSocket 原生支持需要额外配置
动态路由支持不支持

3. lb:// 协议是如何工作的?

lb://service-name 是 Gateway 内置的负载均衡协议,其实现依赖 Spring Cloud LoadBalancer。Gateway 从 Nacos 发现目标服务的所有实例,通过 LoadBalancer 选择一个实例,替换 lb:// 为实际 http://IP:PORT。

4. Gateway 如何实现灰度发布?

两种方式:

  • Weight 断言:- Weight=group1, 80 和 - Weight=group2, 20,按权重将流量分发到不同的 uri。
  • 结合 Nacos 元数据:在 Nacos 中为实例标记版本信息,自定义 LoadBalancer 规则按元数据路由。

5. 如何实现 Gateway 的高可用?

  • Gateway 本身是无状态应用,通过部署多个实例 + Nginx/SLB 前置实现水平扩展。
  • 注册到 Nacos 后,上游 Nginx 通过健康检查发现异常 Gateway 节点并剔除。
  • 限流依赖的 Redis 建议使用哨兵/集群模式保证高可用。

参考资源:

  • Spring Cloud Gateway 官方文档:https://docs.spring.io/spring-cloud-gateway
  • Gateway + Nacos 集成:https://sca.aliyun.com
上一页
Dubbo RPC服务调用
下一页
GraalVM静态编译