Zuul、Gateway 和 Nginx 有什么区别?
结论先行:三者不是同一层的东西。Nginx 是 C 语言写的反向代理/负载均衡服务器,位于接入层,擅长 TLS 卸载、静态资源与四层转发;Zuul 1 是 Netflix 基于 Servlet 的阻塞式网关,已进入维护模式;Spring Cloud Gateway 基于 WebFlux + Netty 的响应式网关,是 Zuul 1 的官方替代品。
1. 架构与线程模型
Nginx: master 进程 + N 个 worker 进程(每进程单线程 epoll)
请求在 worker 内事件驱动,无阻塞
Zuul 1: Servlet 容器(Tomcat)+ 每请求一线程
过滤器链在请求线程里同步执行,调下游时线程阻塞
Gateway: Netty EventLoop + Reactor
路由、过滤、转发都是异步链路,少量线程扛大量并发
线程模型决定了并发能力:Zuul 1 在慢下游场景下线程会被占满,Gateway 则不会。
2. 能力对比
| 维度 | Nginx | Zuul 1 | Spring Cloud Gateway |
|---|---|---|---|
| 语言/生态 | C,独立于 JVM | Java,Spring 生态 | Java,Spring 生态 |
| 线程模型 | 事件驱动多进程 | Servlet 阻塞 | Netty 响应式 |
| 动态路由 | 改配置 + reload | 可编程(Filter) | 可编程(Route/Filter) |
| 服务发现集成 | 需手工/脚本同步 | 可接 Eureka | 原生 lb:// |
| 鉴权/限流 | 需 lua/第三方模块 | 过滤器实现 | 过滤器 + Redis 限流 |
| 性能 | 极高(静态/转发) | 一般 | 高 |
| 运维复杂度 | 低(成熟) | 中 | 中 |
| 现状 | 活跃 | 维护模式 | 活跃(官方主推) |
3. 配置对照
Nginx:
upstream order_service {
server 10.0.0.11:8082;
server 10.0.0.12:8082;
}
server {
listen 80;
server_name api.example.com;
location /api/order/ {
proxy_pass http://order_service/;
proxy_set_header X-Real-IP $remote_addr;
}
}
Zuul 1:
zuul:
routes:
order-service:
path: /api/order/**
serviceId: order-service
stripPrefix: true
Gateway:
spring:
cloud:
gateway:
routes:
- id: order_route
uri: lb://order-service
predicates:
- Path=/api/order/**
filters:
- StripPrefix=1
后两者的差异在于:Gateway 的断言与过滤器是一等公民,且支持响应式编程;Zuul 1 的过滤器只能同步阻塞地调用下游。
4. Zuul 2 为什么没流行
Zuul 2 改成了 Netty 异步模型,性能大幅提升,但 Netflix 开源节奏放缓、Spring Cloud 官方未集成(Spring Cloud Netflix 只维护 Zuul 1),社区于是转向 Gateway。今天新项目不应再选 Zuul。
5. 实际拓扑:三者共存
客户端
│ HTTPS
▼
Nginx(TLS 卸载、静态资源、限流、WAF)
│ HTTP
▼
Spring Cloud Gateway × N(鉴权、路由、灰度、按服务限流)
│ lb://
▼
业务服务(order / user / stock)
分工原则:Nginx 管「接入」,Gateway 管「业务入口」。把鉴权写在 Nginx 里需要 lua 且难以复用 Spring 的 Bean;把静态资源交给 Gateway 又会浪费 JVM 内存。
6. 常见追问
追问一:Gateway 能替代 Nginx 吗? 不能完全替代。Gateway 是 JVM 应用,处理静态文件和高并发 TLS 不如 Nginx;但业务级路由、鉴权、灰度它更强。生产上二者叠加使用。
追问二:为什么 Zuul 1 在高并发下容易线程耗尽? 它每个请求占用一个 Servlet 线程,调用下游时线程阻塞等待。下游 RT 一高,线程池迅速打满,新请求排队。Gateway 用少量 EventLoop 线程处理海量连接,等待不占线程。
追问三:Nginx 能做服务发现吗?
可以,通过 resolver + 变量 proxy_pass 或 OpenResty + Lua 读注册中心,但实现复杂。K8s 场景下可用 Service/DNS 替代。
追问四:Gateway 的过滤器顺序怎么定?
实现 Ordered 接口,getOrder() 越小越先执行。GlobalFilter 与路由级 GatewayFilter 会被合并排序,NettyRoutingFilter 是最后真正发请求的那个。
追问五:三者性能差距有多大? 单纯转发场景 Nginx 最高(C + epoll),Gateway 次之(Netty),Zuul 1 最低(阻塞 Servlet)。但网关通常不是瓶颈,业务服务的 RT 才是。
小结
选型只需记住层级:接入层用 Nginx,业务网关用 Gateway,Zuul 只存在于历史项目。它们的差别不在「谁更强」,而在「谁该负责哪一段」——把 TLS 和静态资源交给 Nginx,把鉴权与路由交给 Gateway,是最省心的组合。