从一个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) │
│ 服务发现与健康检查 │
└─────────────────────────────────┘
实际请求流程:
-
用户访问
https://api.example.com/user/profile -
Nginx 处理:
-
验证HTTPS证书
-
检查这个IP是不是在黑名单里
-
如果是图片请求,直接从缓存返回
-
否则转发给 Spring Cloud Gateway
-
-
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),它们各司其职,共同守护着系统安全。