文章目录
- [Ⅰ. 网关介绍](#Ⅰ. 网关介绍)
-
- 一、问题
- 二、什么是API网关
- 三、常见网关实现
-
- [1️⃣ Spring Cloud Gateway(主流首选)](#1️⃣ Spring Cloud Gateway(主流首选))
- [2️⃣ Zuul(Zuul 1 / Zuul 2)](#2️⃣ Zuul(Zuul 1 / Zuul 2))
- [3️⃣ Nginx / OpenResty](#3️⃣ Nginx / OpenResty)
- [4️⃣ Envoy](#4️⃣ Envoy)
- [5️⃣ Kong](#5️⃣ Kong)
- [6️⃣ Traefik](#6️⃣ Traefik)
- [7️⃣ 云厂商网关](#7️⃣ 云厂商网关)
- [Ⅱ. Spring Cloud Gateway](#Ⅱ. Spring Cloud Gateway)

Ⅰ. 网关介绍
一、问题
前面学习中通过 Eureka、Nacos 解决了服务注册、服务发现的问题,使用 Spring Cloud LoadBalance 解决了负载均衡的问题,使用 OpenFeign 解决了远程调用的问题。
但是当前所有微服务的接口都是直接对外暴露的,可以直接通过外部访问。为了保证对外服务的安全性,服务端实现的微服务接口通常都带有一定的权限校验机制。并且由于使用了微服务,原本一个应用的的多个模块拆分成了多个应用,我们不得不实现多次校验逻辑。当这套逻辑需要修改时,需要同时修改多个应用,这加重了开发人员的负担。
为了解决以上问题,可以使用 API 网关。
二、什么是API网关
API网关(简称网关)也是一个服务,通常是后端服务的唯一入口。它的定义类似设计模式中的 Facade 模式(门面模式,也称外观模式)。
它就类似整个微服务架构的门面,所有的外部客户端访问,都需要经过它来进行调度和过滤。
但它比门面模式的功能要丰富很多,经典门面模式只是接口封装 ,不关心网络、路由、安全、限流;而 API 网关是一个企业级流量治理层,还承担了鉴权、路由、限流等基础设施能力。
| 维度 | 代码级 Facade | Spring Cloud Gateway |
|---|---|---|
| 层级 | 应用内 | 系统边界 |
| 关注点 | 业务流程 | 流量 & 安全 |
| 调用方式 | 方法调用 | HTTP / WebFlux |
| 是否有业务逻辑 | 少 | 几乎没有 |
| 是否是门面思想 | ✔ | ✔(强化版) |

网关核心功能:
- 统一入口(门面)
- 屏蔽内部服务拓扑
- 依赖收敛
- 路由
- 鉴权
- 限流
- 熔断
- 监控
- 协议转换
三、常见网关实现
1️⃣ Spring Cloud Gateway(主流首选)
定位:官方微服务网关
技术栈:WebFlux + Reactor(非阻塞)
核心能力
- 动态路由(基于服务发现)
- 全局 / 局部 Filter
- 鉴权、限流、熔断
- 与 Spring Cloud 生态深度集成
适用场景
- Spring Cloud 微服务
- 需要统一鉴权、限流、监控
评价
企业级标配,99% Java 微服务项目首选
2️⃣ Zuul(Zuul 1 / Zuul 2)
定位:早期 Netflix 网关
- Zuul 1:阻塞式(Servlet)
- Zuul 2:异步(但生态断层)
现状
- 已被 Spring Cloud Gateway 取代
- 新项目不推荐
面试话术
Zuul 是历史方案,Gateway 是演进方案
3️⃣ Nginx / OpenResty
定位:反向代理 / 七层网关
核心能力
- 反向代理、负载均衡
- SSL 终止
- 限流、黑白名单
- OpenResty 可写 Lua 扩展逻辑
适用场景
- 网关最前置一层
- 高并发、低延迟
- 简单路由 + 防护
典型架构
Plain
Client
↓
Nginx
↓
Spring Cloud Gateway
4️⃣ Envoy
定位:云原生 / Service Mesh 网关
核心能力
- 高性能 L7 Proxy
- gRPC / HTTP2
- 动态配置(xDS)
- 可观测性极强
适用场景
- Kubernetes
- Istio / Service Mesh
- 大规模微服务
评价
技术先进,但学习成本高
5️⃣ Kong
定位:基于 Nginx 的 API Gateway
核心能力
- 插件化(鉴权、限流、日志)
- REST / gRPC
- 多语言支持
适用场景
- 多语言微服务
- 对外开放 API 平台
6️⃣ Traefik
定位:云原生 Ingress / 网关
核心能力
- 自动发现服务
- Kubernetes 原生友好
- 配置简单
适用场景
- K8s 小中型集群
- DevOps 驱动团队
7️⃣ 云厂商网关
- 阿里云 API 网关
- 腾讯云 API 网关
- AWS API Gateway
适用场景
- 不想自建
- 强依赖云生态
Ⅱ. Spring Cloud Gateway
一、快速上手
① 创建网关项目
API 网关也是一个服务,所以这里单独创建一个 gateway 模块:

② 引入网关依赖
在 gateway 模块中引入网关以及相关依赖:
xml
<!--网关-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!--基于nacos实现服务发现依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!--负载均衡-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
③ 编写启动类
java
@SpringBootApplication
public class GatewayApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayApplication.class,args);
}
}
④ 添加Gateway的路由配置
创建 application.yml 文件,添加如下配置:
yaml
server:
port: 10020 # 网关端口
spring:
application:
name: gateway # 应用名称
cloud:
nacos:
discovery:
server-addr: lirendada.art:8848 # Nacos地址
gateway:
routes:
- id: order-service # 路由id,随便起个名字,不重复即可
uri: lb://order-service # 目标服务地址
predicates: # 路由条件,这里配置路径匹配,匹配到/order/**、/feign/**的请求都转发到order-service服务
- Path=/order/**,/feign/**
- id: product-service
uri: lb://product-service
predicates:
- Path=/product/**
配置字段说明:
id:自定义路由ID,保持唯一即可uri:目标服务地址,支持普通 URI 及lb://应用注册服务名称。lb表示负载均衡,使用lb://方式表示从注册中心获取服务地址。predicates:路由条件,根据匹配结果决定是否执行该请求路由,上述代码中,我们把符合 Path 规则的一切请求,都代理到 uri 参数指定的地址。
⑤ 测试
访问 http://127.0.0.1:10020/product/1001 和 http://127.0.0.1:10020/order/1
二、Route Predicate Factories(路由断言工厂)
① Predicate
Predicate 是 Java8 提供的一个函数式编程接口,它接收一个参数并返回一个布尔值,用于条件过滤、请求参数的校验。其接口声明如下所示:
java
@FunctionalInterface
public interface Predicate<T> {
boolean test(T t);
default Predicate<T> and(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) && other.test(t);
}
default Predicate<T> negate() {
return (t) -> !test(t);
}
default Predicate<T> or(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) || other.test(t);
}
static <T> Predicate<T> isEqual(Object targetRef) {
return (null == targetRef)
? Objects::isNull
: object -> targetRef.equals(object);
}
@SuppressWarnings("unchecked")
static <T> Predicate<T> not(Predicate<? super T> target) {
Objects.requireNonNull(target);
return (Predicate<T>)target.negate();
}
}
代码演示:
-
定义一个
Predicate:javaclass StringPredicate implements Predicate<String> { @Override public boolean test(String str) { return str.isEmpty(); } } -
使用这个
Predicate:javapublic void t1() { Predicate p = new StringPredicate(); System.out.println(p.test("hello")); System.out.println(p.test("")); } // 运行结果: false true -
Predicate的其它写法:java/** * 匿名内部类写法 */ @Test public void t2() { Predicate<String> p = new Predicate<String>() { @Override public boolean test(String s) { return s.length() > 0; } }; System.out.println(p.test("hello")); // true System.out.println(p.test("")); // false } /** * lambda表达式写法 */ @Test public void t3() { Predicate<String> p = s -> s.length() > 0; System.out.println(p.test("hello")); // true System.out.println(p.test("")); // false }
Predicate 的其它方法:
isEqual(Object targetRef):比较两个对象是否相等,参数可以为 Nulland(Predicate other):短路与操作,返回一个组成 Predicateor(Predicate other):短路或操作,返回一个组成 Predicatetest(T t):传入一个 Predicate 参数,用来做判断negate():返回表示此 Predicate 逻辑否定的 Predicate
| 方法 | 说明 |
|---|---|
| Predicate and(Predicate<? super T> other) | 条件A&&条件B 当前Predicate的test方法 && other的test方法,相当于进行两次判断 |
| default Predicate negate() | !条件A 对当前判断取非操作 |
| default Predicate or(Predicate<? super T> other) | 条件A||条件B 当前Predicate的test方法 || other的test方法 |
java
/**
* 非操作
*/
@Test
public void t4() {
Predicate<String> p = s -> s.length() > 0;
System.out.println(p.negate().test("hello")); // false
System.out.println(p.negate().test("")); // true
}
/**
* and操作
*/
@Test
public void t5() {
Predicate<String> p1 = s -> s.length() > 0;
Predicate<String> p2 = s -> s.startsWith("l");
System.out.println(p1.and(p2).test("hello")); // false
System.out.println(p1.and(p2).test("liren")); // true
}
/**
* or操作
*/
@Test
public void t6() {
Predicate<String> p1 = s -> s.length() > 0;
Predicate<String> p2 = s -> s.startsWith("l");
System.out.println(p1.or(p2).test("hello")); // true
System.out.println(p1.or(p2).test("liren")); // true
System.out.println(p1.or(p2).test("")); // false
}
② Route Predicate Factories
在 Spring Cloud Gateway 中,Predicate 提供了路由规则的匹配机制:
yaml
spring:
cloud:
gateway:
routes: # 网关路由配置
- id: product-service
uri: lb://product-service
predicates:
- Path=/product/**
我们在配置文件中写的断言规则只是字符串,这些字符串会被 Route Predicate Factory 读取并处理,转变为路由判断的条件。
比如例子中配置的 Path=/product/**,就是通过 Path 属性来匹配 URL 前缀是 /product 的请求。这个规则是由 org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactory 实现的。
SpringCloudGateway 默认提供了很多 RoutePredicateFactory,这些 Predicate 会分别匹配 HTTP 请求的不同属性,并且多个 Predicate 可以通过 and 逻辑进行组合。
| 断言 | 作用 |
|---|---|
| Path | 路径匹配 |
| Method | HTTP 方法 |
| Header | 请求头 |
| Query | 请求参数 |
| Cookie | Cookie |
| Host | 域名 |
| After | 指定时间后 |
| Before | 指定时间前 |
| Between | 时间区间 |
| RemoteAddr | 客户端 IP |
| Weight | 权重 |
代码演示
-
在
application.yml中添加Predicate规则,新增一个After条件:yamlspring: cloud: gateway: routes: # 网关路由配置 - id: product-service uri: lb://product-service predicates: - Path=/product/** - After=2025-12-13T14:08:33.643172900+08:00[Asia/Shanghai] # 请求时间为2025年12月13日之后 -
测试:访问 http://127.0.0.1:10020/product/1001,然后修改时间为 2026-01-01,再次访问
