Nginx和Spring Cloud Gateway

从一个Java新手的视角,聊聊这两个经常让人傻傻分不清的网关组件

一、它们都是"看门人"

想象一下,你住在一个大型小区里:

  • Nginx 就像是小区的大门保安,对所有进出的人进行初步检查和分流

  • Spring Cloud Gateway 更像是你家的智能门锁,能识别具体是谁来了,并决定让不让他进哪个房间

虽然角色不同,但它们确实有很多相似的地方。

1. 都能做"指路"(路由转发)

Nginx的做法(修改nginx.conf):

nginx

复制代码
# 用户访问 http://你的服务器/user/xxx 时
location /user/ {
    # 转发到用户服务
    proxy_pass http://user-service:8080/;
}

location /order/ {
    # 转发到订单服务
    proxy_pass http://order-service:8081/;
}

Spring Cloud Gateway的做法(application.yml):

yaml

复制代码
spring:
  cloud:
    gateway:
      routes:
        # 用户访问 /user/** 时
        - id: user-route
          uri: lb://user-service  # lb:// 表示从注册中心获取地址
          predicates:
            - Path=/user/**
            
        - id: order-route
          uri: lb://order-service
          predicates:
            - Path=/order/**

相似之处:都是根据请求的路径,决定转发到哪个后端服务。

2. 都能做"分流"(负载均衡)

Nginx的做法

nginx

复制代码
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;     # 备用服务器
}

location /user/ {
    proxy_pass http://user-cluster/;
}

Spring Cloud Gateway的做法

yaml

复制代码
# 配合注册中心使用,自动实现负载均衡
spring:
  cloud:
    gateway:
      routes:
        - id: user-route
          uri: lb://user-service  # lb:// 自动负载均衡
          predicates:
            - Path=/user/**

相似之处:都能把请求分发到多个服务实例,避免单个服务压力过大。

3. 都能做"安检"(过滤器/拦截器)

Nginx的做法(检查请求头):

nginx

复制代码
location /api/ {
    # 检查有没有token
    if ($http_authorization = "") {
        return 401;  # 没有token,拒绝访问
    }
    proxy_pass http://backend/;
}

Spring Cloud Gateway的做法(Java代码):

java

复制代码
@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 || token.isEmpty()) {
            // 没有token,返回401
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
            return exchange.getResponse().setComplete();
        }
        
        return chain.filter(exchange);
    }
}

相似之处:都能在请求到达后端之前进行拦截和校验。

4. 都能做"限流"(保护后端)

Nginx的做法

nginx

复制代码
# 限制每个IP每秒最多10个请求
limit_req_zone $binary_remote_addr zone=mylimit:10m rate=10r/s;

location /api/ {
    limit_req zone=mylimit burst=20;
    proxy_pass http://backend/;
}

Spring Cloud Gateway的做法(配合Redis):

yaml

复制代码
spring:
  cloud:
    gateway:
      routes:
        - id: api-route
          uri: lb://api-service
          filters:
            - name: RequestRateLimiter
              args:
                redis-rate-limiter.replenishRate: 10  # 每秒10个令牌
                redis-rate-limiter.burstCapacity: 20  # 最大20个令牌

相似之处:都能防止后端服务被突发的流量冲垮。

二、它们其实很不一样

看到这里,你可能会想:"这不是差不多吗?"别急,让我们看看它们本质的区别。

1. 一个是"保安",一个是"智能管家"

对比维度 Nginx Spring Cloud Gateway
身份 Web服务器/反向代理 API网关
出身 C语言,性能怪兽 Java语言,Spring家族
擅长 高并发、静态资源、网络层处理 业务逻辑、服务治理、协议转换

2. 性能差异:C语言 vs Java

Nginx

  • 内存占用:几十MB

  • 并发能力:单机5万+连接轻轻松松

  • 启动速度:秒级启动

Spring Cloud Gateway

  • 内存占用:300MB起步(JVM开销)

  • 并发能力:单机几千到上万(受GC影响)

  • 启动速度:几十秒(Spring Boot启动慢)

3. 配置方式:配置 vs 代码

Nginx是配置驱动:

nginx

复制代码
# 改完配置需要reload
server {
    listen 80;
    location / {
        proxy_pass http://backend;
    }
}

Spring Cloud Gateway是代码驱动:

java

复制代码
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
    return builder.routes()
        .route("user_route", r -> r.path("/user/**")
            .filters(f -> f.filter(new MyCustomFilter()))  // 可以写任意复杂的逻辑
            .uri("lb://user-service"))
        .build();
}

4. 对微服务的感知能力

Nginx

  • 不知道后端服务是死是活

  • 需要手动配置服务地址

  • 服务地址变了,需要修改配置并reload

Spring Cloud Gateway

  • 自动从注册中心(Nacos、Eureka)发现服务

  • 自动感知服务健康状态

  • 服务地址变了,自动更新,无需重启

yaml

复制代码
# Spring Cloud Gateway 配合 Nacos 使用
spring:
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848  # 服务自动发现
    gateway:
      routes:
        - id: user-service
          uri: lb://user-service  # 自动从Nacos获取地址
          predicates:
            - Path=/user/**

5. 对业务逻辑的支持

Nginx:想做复杂业务逻辑?写Lua脚本吧(学习曲线陡峭)

lua

复制代码
-- 需要在Nginx中写Lua代码
local json = require("cjson")
local token = ngx.var.http_authorization
local claims = jwt:verify(token, "secret")  -- 解析JWT
if claims.role ~= "admin" then
    ngx.exit(403)
end

Spring Cloud Gateway:写Java代码就行

java

复制代码
@Component
public class AuthFilter implements GlobalFilter {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 写Java代码,就是舒服
        String token = exchange.getRequest().getHeaders().getFirst("Authorization");
        JWT jwt = JWT.decode(token);
        String role = jwt.getClaim("role").asString();
        
        if (!"admin".equals(role)) {
            exchange.getResponse().setStatusCode(HttpStatus.FORBIDDEN);
            return exchange.getResponse().setComplete();
        }
        
        // 还可以把用户信息传给下游服务
        exchange.getRequest().mutate()
            .header("X-User-Id", jwt.getClaim("userId").asString())
            .build();
        
        return chain.filter(exchange);
    }
}

三、实际架构中它们是怎么配合的?

在实际项目中,Nginx 和 Spring Cloud Gateway 不是二选一,而是各司其职、互相配合

一个典型的微服务架构是这样的:

text

复制代码
                    ┌─────────────────────────────────┐
                    │         用户/管理员/运营         │
                    └─────────────────────────────────┘
                                      │
                                      ▼
                    ┌─────────────────────────────────┐
                    │            Nginx                │
                    │  职责:边界网关                 │
                    │  - HTTPS证书管理                │
                    │  - 防DDoS攻击                   │
                    │  - 静态资源(图片、CSS)         │
                    │  - 按域名分流                    │
                    └─────────────────────────────────┘
                                      │
                                      ▼
                    ┌─────────────────────────────────┐
                    │     Spring Cloud Gateway        │
                    │  职责:业务网关                  │
                    │  - 统一鉴权(JWT校验)           │
                    │  - 路由到具体微服务              │
                    │  - 限流熔断                      │
                    │  - 灰度发布                      │
                    │  - 请求日志                      │
                    └─────────────────────────────────┘
                                      │
        ┌─────────────────┬───────────┴───────────┬─────────────────┐
        ▼                 ▼                       ▼                 ▼
┌─────────────┐   ┌─────────────┐         ┌─────────────┐   ┌─────────────┐
│  用户服务    │   │  订单服务    │         │  商品服务    │   │  权限服务    │
└─────────────┘   └─────────────┘         └─────────────┘   └─────────────┘
        │                 │                       │                 │
        └─────────────────┴───────────┬───────────┴─────────────────┘
                                      ▼
                    ┌─────────────────────────────────┐
                    │        服务注册中心(Nacos)      │
                    │        服务发现与健康检查         │
                    └─────────────────────────────────┘

实际请求流程:

  1. 用户访问 https://api.example.com/user/profile

  2. Nginx 处理:

    • 验证HTTPS证书

    • 检查这个IP是不是在黑名单里

    • 如果是图片请求,直接从缓存返回

    • 否则转发给 Spring Cloud Gateway

  3. Spring Cloud Gateway 处理:

    • 校验JWT Token

    • 根据 /user/ 路径,从Nacos获取用户服务的地址

    • 把请求转发给用户服务

    • 记录请求日志

四、新手该如何选择?

场景一:你只是在做一个小项目

  • 用 Nginx 就够了

  • 原因:轻量、简单、性能好

场景二:你正在做一个微服务项目,且用的是Spring Cloud全家桶

  • 用 Spring Cloud Gateway

  • 原因:和Spring生态无缝集成,写代码就能实现复杂逻辑

场景三:你做的项目要上线,有公网访问

  • 两个都要用

  • Nginx 在最外层处理网络层问题

  • Spring Cloud Gateway 在内层处理业务逻辑

五、新手常见疑问

Q1:Nginx能完全替代Spring Cloud Gateway吗?

不能。Nginx做业务逻辑太痛苦了(除非你想写Lua脚本),而且Nginx没有服务发现能力。

Q2:Spring Cloud Gateway能完全替代Nginx吗?

也不能。Spring Cloud Gateway处理静态资源效率不如Nginx,而且也没有Nginx那么多网络层的功能(比如HTTPS证书管理、IP黑白名单等)。

Q3:我该先学哪个?

如果你主要写Java:

  • 先学 Spring Cloud Gateway,因为用Java写,上手快

  • 然后了解 Nginx 的基本配置

如果你主要做运维:

  • 先学 Nginx,因为这是运维的基本功

  • 然后了解 Spring Cloud Gateway 的配置方式

Q4:性能差多少?

  • Nginx:单机轻松支持 5万+ QPS

  • Spring Cloud Gateway:单机一般 5000-10000 QPS(取决于业务逻辑)

但大多数中小项目,10000 QPS 已经绰绰有余了。

写在最后

作为新手,不用纠结"到底该用哪个"。记住一个简单的原则:

  • Nginx 负责"外面"的事:安全、静态资源、流量分发

  • Spring Cloud Gateway 负责"里面"的事:业务逻辑、服务治理

就像小区门口有保安(Nginx),楼里有智能门禁(Gateway),它们各司其职,共同守护着系统安全。

相关推荐
困惑阿三2 小时前
全栈部署排雷手册:从 405 报错到飞书推送成功
服务器·前端·后端·nginx·阿里云·node.js·飞书
熬夜的咕噜猫2 小时前
Nginx 安全防护与 HTTPS 部署实战
网络·数据库
xiaozhazha_2 小时前
再生资源行业数字化平台建设实践:快鹭AI从痛点分析到微服务架构落地
人工智能·微服务·架构
神的孩子都在歌唱2 小时前
无线网络基础:802.11协议、信道干扰与加密方式
网络
Elastic 中国社区官方博客2 小时前
测试 Elasticsearch,现在变得更简单了
大数据·运维·elasticsearch·搜索引擎·全文检索
野犬寒鸦2 小时前
从零起步学习JVM|| 第二章:JVM基本组成及JVM内存区域详解
服务器·开发语言·后端·学习·面试·职场和发展
vx-bot5556662 小时前
企业微信ipad协议的防封号技术体系与策略实践
服务器·企业微信·ipad
木子欢儿2 小时前
在 Debian 12 上安装多个版本的 php(7.3、7.4、8.1、8.2)
运维·开发语言·debian·php
DJ斯特拉2 小时前
Docker基本使用
运维·docker·容器