Gateway路由怎么写?

wen python案例 2

Gateway路由配置实战指南(附完整问答)

📖 目录导读

  1. 为什么需要API网关? – 网关的核心价值与适用场景
  2. Gateway路由核心概念 – 路由、断言、过滤器的关系
  3. 手把手写第一个路由 – Spring Cloud Gateway配置步骤
  4. 路由规则深度解析 – path/host/header/query断言实战
  5. 过滤器链与自定义扩展 – 请求改写、限流、重试
  6. 动态路由配置方案 – 从配置文件到数据库+Redis
  7. 高可用与安全加固 – 跨域、认证、防火墙策略
  8. 常见问题与问答 – 路由不生效、循环转发、性能调优

为什么需要API网关?

在微服务架构中,服务被拆分为数十个独立模块,客户端直连后端会面临:

Gateway路由怎么写?

  • 认证逻辑重复:每个服务都要校验token
  • 路由混乱:前端需要维护多个服务地址
  • 跨域与安全:无法统一处理CORS和流量控制

网关作为系统唯一入口,承担路由分发、鉴权、限流、日志记录等横切关注点。


Gateway路由核心概念

1 三要素

组件 作用 示例
Route(路由) 定义请求匹配规则与转发目标 /api/user/** → user-service
Predicate(断言) 判断请求是否符合条件 路径、请求头、时间、Cookie
Filter(过滤器) 在请求前后执行增强逻辑 添加Header、重写路径、熔断

2 工作流程

请求 → Gateway → [断言匹配] → [过滤器链] → 转发目标服务 → 响应返回

手把手写第一个路由

1 环境准备

<!-- pom.xml -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

2 基础路由配置(application.yml)

spring:
  cloud:
    gateway:
      routes:
        - id: user_route               # 路由唯一ID
          uri: lb://user-service       # 负载均衡方式转发
          predicates:
            - Path=/api/user/**        # 匹配 /api/user/ 开头的请求
          filters:
            - StripPrefix=1            # 去掉第一级路径 /api

测试:访问 http://网关:8080/api/user/info → 转发到 http://user-service/info


路由规则深度解析

1 常用断言(Predicate)

predicates:
  # 路径匹配:支持Ant风格通配符
  - Path=/api/order/**,/api/payment/{segment}
  # 请求头匹配:包含X-Request-Id且值为数字
  - Header=X-Request-Id, \d+
  # 查询参数匹配:存在token参数
  - Query=token
  # 请求方法匹配
  - Method=GET,POST
  # 时间范围:仅允许工作时间访问
  - Between=2025-03-01T00:00:00+08:00, 2025-03-31T23:59:59+08:00

2 多条件组合路由

- id: api_v2_route
  uri: https://newapi.example.com
  predicates:
    - Path=/api/v2/** 
    - Header=Version, 2.0
    - RemoteAddr=192.168.1.0/24   # 仅允许内网访问

过滤器链与自定义扩展

1 内置过滤器示例

filters:
  # 改写请求路径
  - RewritePath=/api/(?<segment>.*), /$\{segment}
  # 添加请求头
  - AddRequestHeader=Gateway-From, gateway-client
  # 设置响应头
  - AddResponseHeader=X-Response-Time, ${gateway.timestamp}
  # 熔断降级(配合Resilience4j)
  - name: CircuitBreaker
    args:
      name: orderCircuitBreaker
      fallbackUri: forward:/fallback/order

2 自定义过滤器(Java代码)

@Component
public class AuthFilter implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        String token = exchange.getRequest().getHeaders().getFirst("Authorization");
        if (token == null || !token.startsWith("Bearer ")) {
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
            return exchange.getResponse().setComplete();
        }
        // 校验成功继续转发
        return chain.filter(exchange);
    }
    @Override
    public int getOrder() {
        return -100; // 高优先级
    }
}

动态路由配置方案

1 方案对比

方案 优点 缺点
配置文件静态路由 简单直观 需要重启网关
数据库+定时刷新 实时性中等 数据一致性问题
Nacos/Zookeeper配置中心 实时生效 依赖外部组件
Redis路由缓存 高性能、动态 需额外开发管理界面

2 Nacos动态路由实现

# bootstrap.yml
spring:
  cloud:
    nacos:
      config:
        server-addr: 127.0.0.1:8848
        data-id: gateway-routes.yml
        group: DEFAULT_GROUP
        refresh-enabled: true  # 自动刷新

配置中心数据:

spring:
  cloud:
    gateway:
      routes:
        - id: dynamic_route
          uri: lb://inventory-service
          predicates:
            - Path=/inventory/**

高可用与安全加固

1 跨域配置

spring:
  cloud:
    gateway:
      globalcors:
        corsConfigurations:
          '[/**]':
            allowedOriginPatterns: "*"    # 生产环境应限定域名
            allowedMethods: "*"
            allowedHeaders: "*"
            allowCredentials: true

2 安全最佳实践

  • 禁用Gateway本身端点management.endpoints.web.exposure.exclude=gateway
  • 限制IP白名单GatewayFilter + RemoteAddr断言
  • 防止重复认证:使用RequestRateLimiter过滤器做限流
  • HTTPS强制跳转HttpsRedirectFilter
@Bean
public RouteLocator customRoutes(RouteLocatorBuilder builder) {
    return builder.routes()
        .route("secure_route", r -> r.path("/api/secure/**")
            .filters(f -> f.hystrix(config -> config.setFallbackUri("forward:/fallback")))
            .uri("https://secure-backend.com"))
        .build();
}

常见问题与问答

❓ Q1:路由配置后访问404

排查步骤

  1. 检查断言路径是否正确匹配:/api/user 不等于 /api/user/
  2. 确认服务注册名与urilb://后的名称一致
  3. 查看网关日志:DEBUG级别打印路由匹配过程
logging:
  level:
    org.springframework.cloud.gateway: DEBUG

❓ Q2:网关循环转发

原因:目标服务地址错误写成了网关自身的地址。
解决:检查uri是否指向真实服务,避免使用localhost0.0.1

❓ Q3:自定义过滤器不生效

检查点

  • 是否添加@Component注解
  • 是否实现Ordered接口并设置优先级
  • 过滤器顺序值越小越先执行

❓ Q4:如何做到灰度发布?

方案:通过Weight断言实现流量分发

- id: v1_route
  uri: lb://service-v1
  predicates:
    - Path=/api/**
    - Weight=service_group, 80  # 80%流量
- id: v2_route
  uri: lb://service-v2
  predicates:
    - Path=/api/**
    - Weight=service_group, 20  # 20%流量

❓ Q5:Gateway和Zuul如何选择?

对比维度 Spring Cloud Gateway Zuul 1.x
编程模型 响应式(WebFlux) 同步阻塞(Servlet)
吞吐量 更高(异步非阻塞) 相对较低
配置灵活性 支持Java DSL和YAML 主要基于Filter
社区活跃度 当前主流选择 已处于维护模式

推荐:新项目直接使用Gateway,低并发旧系统可继续使用Zuul。


如何写出生产级Gateway路由?

  1. 最小权限原则:限定路径、方法、IP范围
  2. 统一错误处理:自定义ErrorWebExceptionHandler
  3. 配置可观测:集成Micrometer暴露网关指标
  4. 路由治理:通过配置中心实现动态路由,避免停机重启
  5. 安全审计:记录所有被拒绝的请求到ELK日志系统

实践建议:先从YAML静态路由开始,熟悉断言和过滤器后,再迁移到数据库动态路由,遇到路由不匹配时,优先开启DEBUG日志分析断言结果。


问题或补充?欢迎在评论区提出,一起完善网关配置最佳实践。

抱歉,评论功能暂时关闭!