Gateway 和 Nginx 路由区别

定位

Spring Cloud Gateway 和 Nginx 都是常见的流量入口组件,但它们的定位和能力有本质区别。简单来说:Nginx 是"高性能反向代理服务器",Gateway 是"微服务网关",二者不是替代关系,而是互补协作。


核心定位对比

维度 Nginx Spring Cloud Gateway
定位 高性能反向代理/Web服务器 微服务 API 网关
开发语言 C 语言,独立部署 Java,依赖 Spring Boot/Cloud
层级 最外层(边缘网关/流量网关) 第二层(业务/微服务网关)
内存占用 几十 MB 300MB 起步(JVM 开销)
单机 QPS 5~10 万+ 1~3 万左右

一个形象的比喻:Nginx 是"小区大门",管所有进出;Gateway 是"楼栋门禁",管具体单元的精细权限。


能力差异详解

Nginx 擅长的领域
  • 静态资源服务:直接提供 HTML/CSS/JS/图片等,支持缓存、gzip 压缩,性能极强
  • SSL/TLS 终结:高效处理 HTTPS,支持 TLS 1.3,证书管理方便
  • 基础安全防护:配合 fail2ban、WAF 模块,DDoS 防护成熟
  • 通用负载均衡:支持多语言后端(Java、Node.js、Python 等),不绑定技术栈
  • 极限性能:C 语言实现,事件驱动模型,单机轻松抗住万级 QPS
Gateway 擅长的领域
  • 动态路由/服务发现:原生集成 Nacos/Eureka/Consul,自动感知服务上下线,无需重启
  • 业务过滤器:用 Java 代码编写 GlobalFilter,开发调试便捷(Nginx 需写 Lua 脚本,学习成本高)
  • 微服务治理:集成熔断(Sentinel)、灰度发布、请求聚合、指标埋点等
  • 统一认证:JWT 校验、Token 解析等用 Java 实现更灵活

相同功能的不同实现方式

两者都能做负载均衡、限流、鉴权,但实现方式差异很大:

负载均衡
nginx 复制代码
# Nginx:手动配置服务地址,服务变了需 reload
upstream user-cluster {
    server 192.168.1.10:8080 weight=3;
    server 192.168.1.11:8080 weight=1;
    server 192.168.1.12:8080 backup;
}
yaml 复制代码
# Gateway:自动从注册中心发现服务,无需手动维护地址
spring:
  cloud:
    gateway:
      routes:
        - id: user-route
          uri: lb://user-service   # lb:// 自动负载均衡
          predicates:
            - Path=/user/**
鉴权
nginx 复制代码
# Nginx:简单的请求头检查
location /api/ {
    if ($http_authorization = "") {
        return 401;
    }
    proxy_pass http://backend/;
}
java 复制代码
// Gateway:可以写复杂的 JWT 解析、权限校验逻辑
@Component
public class AuthFilter implements GlobalFilter {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        String token = exchange.getRequest().getHeaders().getFirst("Authorization");
        if (token == null || !jwtUtil.verify(token)) {
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
            return exchange.getResponse().setComplete();
        }
        return chain.filter(exchange);
    }
}

性能实测参考

根据压测数据(4核8G 云服务器环境):

并发数 Gateway 平均响应时间 Nginx 平均响应时间 差距
100 12.3ms 8.7ms Nginx 快 41%
500 18.9ms 15.2ms Nginx 快 24%
1000 25.4ms 28.7ms Gateway 反超 11%
2000 42.1ms 56.3ms Gateway 快 25%

低并发时 Nginx 凭借 C 语言优势领先;高并发时 Gateway 的响应式模型(WebFlux + Netty)反超。


实际架构中如何搭配

生产环境中最常见的做法是 Nginx + Gateway 组合使用

复制代码
用户请求
  ↓
Nginx(最外层)
  → SSL 卸载(HTTPS → HTTP)
  → 静态资源直接返回
  → 基础限流/DDoS 防护
  → 负载均衡到多个 Gateway 实例
  ↓
Spring Cloud Gateway(第二层)
  → 动态路由(配合 Nacos 服务发现)
  → 统一认证(JWT 校验)
  → 熔断限流(Sentinel)
  → 灰度发布、请求日志
  ↓
微服务集群(User Service / Order Service / ...)
不同场景的选型建议
场景 是否需要 Nginx 推荐方案
中大型项目、QPS > 1万、有公网流量 强烈建议保留 Nginx → Gateway
中小型项目、内部系统、并发不高 可以不要 直接 Gateway
有大量静态资源(图片、前端打包) 必须有 Nginx 负责静态 + Gateway 负责动态
需要极致防护(DDoS、WAF) 必须有 Nginx 做最外层防护

📌 总结 :Nginx 胜在性能极致、资源占用低、通用性强 ;Gateway 胜在与微服务生态深度集成、业务扩展灵活。实际项目中二者是互补关系------Nginx 扛入口流量,Gateway 做业务治理,兼顾高效与灵活。


配置

Nginx 和 Spring Cloud Gateway 之间路由规则对齐、避免重复配置以及常见踩坑

请求完整链路

先理清一个请求从浏览器到微服务的完整路径,后续所有配置都围绕这条链路展开:

复制代码
浏览器 → Nginx(SSL卸载 + 静态资源 + 反向代理)
            ↓
       Gateway(动态路由 + 鉴权 + 限流)
            ↓
       微服务(业务逻辑)

路径前缀对齐:最容易踩坑的地方

这是实际项目中 出现频率最高 的问题。核心原则是:每一层各自剥离自己负责的前缀,不要重复也不要遗漏。

典型三层路径剥离方案

假设前端请求 /app/user/info,最终到达 user-service 的 /info 接口:

层级 进入路径 剥离内容 转出路径
前端 /app/user/info --- /app/user/info
Nginx /app/user/info 剥离 /app /user/info
Gateway /user/info 剥离 /user /info
微服务 /info --- 处理请求
Nginx 配置
nginx 复制代码
# 方案一:proxy_pass 末尾加斜杠,自动剥离 location 前缀
location /app/ {
    proxy_pass http://gateway-upstream/;   # 注意末尾的 /
}

# 方案二:rewrite 显式剥离
location /app/ {
    rewrite ^/app/(.*)$ /$1 break;
    proxy_pass http://gateway-upstream;
}

⚠️ 关键细节proxy_pass 末尾有没有 / 决定了是否自动剥离前缀。

Nginx 配置 请求 /gateway/basic/login 转发到 Gateway 的路径
location /gateway + proxy_pass http://backend /gateway/basic/login /gateway/basic/login(未剥离)
location /gateway/ + proxy_pass http://backend/ /gateway/basic/login /basic/login(已剥离)
Gateway 配置
yaml 复制代码
spring:
  cloud:
    gateway:
      routes:
        - id: user-service
          uri: lb://user-service
          predicates:
            - Path=/user/**        # 匹配 /user/ 开头的请求
          filters:
            - StripPrefix=1        # 剥离 /user,转发 /info
多版本/多环境场景

如果路径有两层前缀(如 /v2/order/add),Gateway 需要配置 StripPrefix=2

yaml 复制代码
- id: order-service-v2
  uri: lb://order-service-v2
  predicates:
    - Path=/v2/order/**
  filters:
    - StripPrefix=2    # 剥离 /v2/order,转发 /add

Header 透传:丢失客户端信息

Nginx 作为反向代理时,默认会修改或丢弃部分请求头。如果配置不当,Gateway 和后端微服务拿不到真实的客户端信息。

必须配置的 Header
nginx 复制代码
location /app/ {
    proxy_pass http://gateway-upstream/;

    # 透传客户端真实 IP
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

    # 透传原始协议(HTTP/HTTPS)
    proxy_set_header X-Forwarded-Proto $scheme;

    # 透传原始 Host
    proxy_set_header Host $host;
}
三个容易混淆的 Host 变量
变量 值来源 是否带端口 适用场景
$http_host 客户端原始 Host 头 带端口 需严格保留客户端 Host
$host 客户端 Host(去端口)或 server_name 不带端口 常规 Web 应用
$proxy_host proxy_pass 中的后端地址 带端口 后端需知道自己真实地址

💡 踩坑提醒:如果后端是 Tomcat,它对 Host 头非常敏感------Host 不匹配会直接返回 404。而 Gateway 只认路径不认 Host,所以"直连 Gateway 正常,经过 Nginx 就 404"的问题,大概率是 Host 头配置错误。

自定义 Header 丢失问题

如果项目中有带下划线的自定义 Header(如 api_key_idrequest_id),Nginx 默认会静默丢弃 。需要在所有 Nginx 层的 http{} 块中统一开启:

nginx 复制代码
http {
    underscores_in_headers on;
    # ...
}

WebSocket 支持:三层都要配

如果项目中有 WebSocket 需求(如实时消息推送),Nginx 和 Gateway 都必须正确配置协议升级,缺一不可。

Nginx 端配置
nginx 复制代码
# 定义 Upgrade 映射(放在 server 块外面)
map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}

location /app/ {
    proxy_pass http://gateway-upstream/;
    proxy_http_version 1.1;                    # 必须用 HTTP/1.1
    proxy_set_header Upgrade $http_upgrade;    # 透传 Upgrade 头
    proxy_set_header Connection $connection_upgrade;  # 协议升级
}
Gateway 端配置
yaml 复制代码
- id: ws-route
  uri: lb:ws://im-service          # 注意 lb:ws:// 协议
  predicates:
    - Path=/im/websocket/**
  filters:
    - StripPrefix=2

⚠️ 多层 Nginx 场景 :如果前面有多层 Nginx(如 SLB → Nginx → Gateway),每一层都必须配置 WebSocket 的 Upgrade 透传,否则握手会失败。


超时配置:长连接被意外断开

Nginx 和 Gateway 的默认超时时间不同,容易出现"Nginx 还没断,Gateway 已经超时"或反过来导致连接中断。

统一超时配置
nginx 复制代码
# Nginx 端
location /app/ {
    proxy_pass http://gateway-upstream/;
    proxy_connect_timeout 10s;     # 连接超时
    proxy_send_timeout 60s;        # 发送超时
    proxy_read_timeout 60s;        # 读取超时
}
yaml 复制代码
# Gateway 端(application.yml)
spring:
  cloud:
    gateway:
      httpclient:
        connect-timeout: 10000     # 连接超时(毫秒)
        response-timeout: 60s      # 响应超时

💡 原则 :Nginx 的超时时间应 略大于 Gateway 的超时时间,让 Gateway 先返回错误信息,而不是 Nginx 直接断开连接返回 502。


限流分工:避免重复或冲突

Nginx 和 Gateway 都能做限流,但应明确分工,避免重复限流导致实际限流阈值远低于预期。

层级 限流策略 工具
Nginx 粗粒度,按 IP 全局限流 limit_req_zone
Gateway 细粒度,按服务/接口/用户限流 Sentinel / Redis RateLimiter
nginx 复制代码
# Nginx:全局限流,每秒 100 请求/IP
limit_req_zone $binary_remote_addr zone=global_rate:10m rate=100r/s;

server {
    location /app/ {
        limit_req zone=global_rate burst=200 nodelay;
        proxy_pass http://gateway-upstream/;
    }
}
yaml 复制代码
# Gateway:针对订单服务精细限流
- id: order-service
  uri: lb://order-service
  predicates:
    - Path=/order/**
  filters:
    - name: RequestRateLimiter
      args:
        redis-rate-limiter.replenishRate: 50    # 每秒令牌数
        redis-rate-limiter.burstCapacity: 100   # 桶容量
        key-resolver: "#{@userKeyResolver}"

排查 404 问题的标准流程

遇到"经过 Nginx 就 404,直连 Gateway 正常"时,按以下步骤排查:

  1. 直连 Gateway 测试curl http://gateway:8080/user/info,确认 Gateway 本身路由没问题
  2. 检查 Nginx 转发路径 :在 Nginx 的 access_log 中确认实际转发给 Gateway 的路径是什么
  3. 检查 proxy_pass 末尾斜杠 :是否意外保留了 /app 前缀
  4. 检查 Host 头:Gateway 的日志中看到的 Host 是否正确
  5. 检查 StripPrefix 数值:Nginx 剥离了一层,Gateway 是否又多剥离或少剥离了

完整生产配置参考

nginx 复制代码
# ===== Nginx 完整配置 =====
upstream gateway-upstream {
    server 192.168.1.100:8080 weight=5;
    server 192.168.1.101:8080 weight=5;
}

# WebSocket 升级映射
map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}

server {
    listen 443 ssl;
    server_name api.example.com;

    # SSL 配置
    ssl_certificate     /etc/nginx/certs/api.example.com.crt;
    ssl_certificate_key /etc/nginx/certs/api.example.com.key;
    ssl_protocols       TLSv1.2 TLSv1.3;

    # 全局 Header 支持
    underscores_in_headers on;

    # 静态资源直接返回,不走 Gateway
    location /static/ {
        root /var/www/frontend;
        expires 7d;
    }

    # API 请求转发到 Gateway
    location /app/ {
        proxy_pass http://gateway-upstream/;

        # 基础 Header 透传
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        # WebSocket 支持
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;

        # 超时配置
        proxy_connect_timeout 10s;
        proxy_read_timeout 60s;
        proxy_send_timeout 60s;

        # 基础限流
        limit_req zone=global_rate burst=200 nodelay;
    }
}
yaml 复制代码
# ===== Gateway 完整配置 =====
spring:
  cloud:
    gateway:
      httpclient:
        connect-timeout: 10000
        response-timeout: 60s
      globalcors:
        add-to-simple-url-handler-mapping: true
        corsConfigurations:
          '[/**]':
            allowedOrigins: "https://example.com"
            allowedHeaders: "*"
            allowedMethods:
              - GET
              - POST
              - PUT
              - DELETE
      routes:
        - id: user-service
          uri: lb://user-service
          predicates:
            - Path=/user/**
          filters:
            - StripPrefix=1

        - id: order-service
          uri: lb://order-service
          predicates:
            - Path=/order/**
          filters:
            - StripPrefix=1

📌 总结 :Nginx 和 Gateway 路由对齐的核心就三件事------路径前缀逐层剥离不重不漏Header 透传完整不丢超时/限流分工明确不冲突。掌握了这三点,基本能覆盖 90% 以上的踩坑场景。

相关推荐
听风3472 小时前
Arch Linux 软件安装完全指南
linux·运维·archlinux·pacman
布兰妮甜2 小时前
跨域全方案对比:CORS、Nginx 反向代理、JSONP、iframe、postMessage
nginx·跨域·cors·前端架构·浏览器安全
沉迷学习 日益消瘦3 小时前
10-Gateway API
运维·kubernetes·gateway
智购科技智能售货柜3 小时前
无人售货机连不上服务器?MQTT 频繁掉线排查全流程~YH
运维·服务器
心念枕惊4 小时前
Docker--Docker Swarm集群
运维·docker·容器
難釋懷4 小时前
Nginx-proxy缓存断点续传缓存 range
运维·nginx·缓存
井川廊咏4 小时前
【总集篇】Linux | 如何创建一个 home 目录在 /data 磁盘的 sudo 用户(补档)
linux·运维·服务器
Kina_C4 小时前
LVS负载均衡的十二种核心调度算法
linux·运维·算法·负载均衡·lvs
AOwhisky5 小时前
Linux(CentOS)系统管理入门笔记(第十五期)——文件系统与存储管理(上篇):设备识别、挂载与文件查找
linux·运维·笔记·centos·文件系统