一、网关介绍
1.1 背景与痛点
在微服务架构中,我们通常通过 Eureka 或 Nacos 解决服务注册与发现问题,利用 Spring Cloud LoadBalancer 实现负载均衡,并通过 OpenFeign 处理远程调用。然而,当所有微服务的接口直接对外暴露时,安全性便成了隐患。
为了保证服务安全,每个微服务内部都需要实现权限校验逻辑。随着服务拆分,原本单体应用中的单一模块变成了多个独立应用,这意味着我们需要在多处重复编写相同的鉴权代码。一旦校验规则需要调整,就必须修改多个应用,极大地增加了开发负担和维护成本。
解决这个问题最通用的方案是引入 API 网关。想象一下企业管理场景:早期只有一个员工负责核实身份;随着部门增多,每个部门都要重复核实流程,效率低下且增加工作量。改进后的做法是设立前台,由前台统一进行身份校验,通过后其他部门直接信任办理。API 网关正是扮演了这个'前台'的角色。
1.2 什么是 API 网关
API 网关(Gateway)是后端服务的唯一入口,其设计模式类似于门面模式(Facade)。它作为整个微服务架构的总控台,所有外部客户端的请求都必须经过它进行调度和过滤。
网关的核心功能主要包括:
- 权限控制:作为入口拦截非法请求,对用户进行身份验证。
- 动态路由:不处理具体业务,而是根据规则将请求转发到对应的微服务。
- 负载均衡:当目标服务有多个实例时,自动分配流量。
- 限流:在流量过高时限制请求,防止后端服务压力过大。
1.3 常见网关实现
业界成熟的网关方案不少,如 Nginx、Kong、Zuul 以及 Spring Cloud Gateway。
Zuul 曾是 Spring Cloud Netflix 的核心组件,但在 2018 年后进入维护状态,不再开发新特性。
Spring Cloud Gateway 是 Spring Cloud 全新的 API 网关项目,基于 Spring Boot 和 WebFlux 技术栈开发,旨在替代 Zuul。官方测试数据显示,其 RPS(每秒请求数)性能约为 Zuul 的 1.6 倍,更适合现代高并发微服务架构。
二、Spring Cloud Gateway 实战
2.1 快速上手
2.1.1 创建网关项目
新建一个标准的 Spring Boot 项目。
2.1.2 引入网关依赖
我们需要引入网关核心依赖、Nacos 服务发现依赖以及负载均衡依赖。
<!-- 网关核心依赖 -->
<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>
2.1.3 编写启动类
标准的 Spring Boot 启动类即可。
@SpringBootApplication
public class GatewayApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayApplication.class, args);
}
}
2.1.4 添加 Gateway 的路由配置
在 application.yml 中配置路由信息,这是网关工作的核心。
server:
port: 10030 # 网关端口
spring:
application:
name: gateway # 服务名称
cloud:
nacos:
discovery:
server-addr: 110.41.51.65:10020
gateway:
routes:
- id: product-service # 路由 ID,自定义,需唯一
uri: lb://product-service # 目标服务地址,lb 表示负载均衡
predicates:
- Path=/product/** # 路由条件,匹配路径前缀
- id: order-service
uri: lb://order-service
predicates:
- Path=/order/**
配置说明:
id:子定义路由 ID,保持唯一。uri:目标服务地址,支持普通 URI 及lb://服务名方式。使用lb://表示从注册中心获取服务地址并做负载均衡。predicates:路由条件,只有匹配该条件的请求才会被转发到指定uri。
访问示例:通过网关访问订单服务,URL 为 http://127.0.0.1:10030/order/1。
2.2 Route Predicate Factories
2.2.1 Predicate 基础
Predicate 是 Java 8 提供的函数式编程接口,接收参数返回布尔值,用于条件过滤。在网关中,它决定了请求是否匹配某个路由规则。
@FunctionalInterface
public interface Predicate<T> {
boolean test(T t);
}
实际使用中,我们可以直接使用 Lambda 表达式简化写法:
Predicate<String> predicate = s -> s.isEmpty();
2.2.2 路由断言工厂
Route Predicate Factories 在 Spring Cloud Gateway 中将配置文件中的字符串规则转换为具体的判断逻辑。例如配置中的 Path=/product/**,实际上是由 PathRoutePredicateFactory 类实现的。
Spring Cloud Gateway 默认提供了丰富的断言工厂,可以匹配 HTTP 请求的不同属性(如时间、IP、Header 等),并且支持通过 and 逻辑组合多个断言。
2.2.3 代码演示
除了路径匹配,我们还可以使用时间断言来限制访问时段。
spring:
cloud:
gateway:
routes:
- id: product-service
uri: lb://product-service
predicates:
- Path=/product/**
- After=2026-01-01T00:00:00.000+08:00[Asia/Shanghai]
这样配置后,只有在指定时间之后的请求才能通过网关。
2.3 Gateway Filter Factories
Predicate 解决了'请求去哪'的问题,而 Filter 则负责在请求转发前后执行额外的逻辑,如鉴权、日志记录等。
Filter 分为两种类型:
- Pre 类型:路由处理之前执行,适合做鉴权、限流。
- Post 类型:响应返回给客户端之前执行,适合做结果处理、日志记录。
Spring Cloud Gateway 从作用范围上将 Filter 分为两类:
- GatewayFilter:应用到单个路由或一组路由上。
- GlobalFilter:应用到所有路由,全局生效。
2.3.1 GatewayFilter
GatewayFilter 通常在配置文件中针对特定路由设置。例如,我们可以为特定路由添加请求参数。
spring:
cloud:
gateway:
routes:
- id: product-service
uri: lb://product-service
predicates:
- Path=/product/**
filters:
- AddRequestParameter=userName,bite
此配置仅对 /product/** 路径下的请求生效,会在请求头中添加 userName=bite 参数。若希望对所有路由生效,可使用 default-filters 配置。
2.3.2 GlobalFilter
GlobalFilter 是全局过滤器,通常用于实现安全性、监控和日志记录等通用功能。Spring Cloud Gateway 内置了许多全局过滤器,如 LoadBalancer Client Filter 负责负载均衡,Gateway Metrics Filter 负责指标收集。
开启监控信息的配置示例:
spring:
cloud:
gateway:
metrics:
enabled: true
management:
endpoints:
web:
exposure:
include: "*"
访问 http://127.0.0.1:10030/actuator 即可查看网关的监控信息。
2.4 过滤器执行顺序
当项目中同时存在 GatewayFilter 和 GlobalFilter 时,网关会将它们合并到一个过滤器链中进行排序执行。每个过滤器都可以通过 order 值指定优先级,数值越小优先级越高。
执行顺序遵循以下原则:
- 按
order值从小到大排序。 - 若
order值相同,默认顺序为:defaultFilter>GatewayFilter>GlobalFilter。
开发者可以通过实现 Ordered 接口或添加 @Order 注解来自定义过滤器的优先级。
2.5 自定义过滤器
为了满足特殊业务需求,开发者可以自定义过滤器,同样支持 GatewayFilter 和 GlobalFilter 两种模式。
2.5.1 自定义 GatewayFilter
自定义 GatewayFilter 需要继承 AbstractGatewayFilterFactory 类。
@Slf4j
@Service
public class CustomGatewayFilterFactory extends AbstractGatewayFilterFactory<CustomConfig> implements Ordered {
public CustomGatewayFilterFactory() {
super(CustomConfig.class);
}
@Override
public GatewayFilter apply(CustomConfig config) {
return ((exchange, chain) -> {
log.info("[Pre] Filter Request, name:" + config.getName());
// 执行后续过滤器链
return chain.filter(exchange).then(Mono.fromRunnable(() -> {
log.info("[Post] Response Filter");
}));
});
}
@Override
public int getOrder() {
return Ordered.LOWEST_PRECEDENCE; // 优先级最低
}
}
配合配置类 CustomConfig 和 YAML 配置使用:
filters:
- name: Custom
args:
name: custom filter
2.5.2 自定义 GlobalFilter
GlobalFilter 的实现更为简单,只需实现 GlobalFilter 接口,无需额外配置即可作用于所有请求。
@Slf4j
@Service
public class CustomGlobalFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
log.info("[Pre] CustomGlobalFilter enter...");
return chain.filter(exchange).then(Mono.fromRunnable(() -> {
log.info("[Post] CustomGlobalFilter return...");
}));
}
@Override
public int getOrder() {
return Ordered.LOWEST_PRECEDENCE;
}
}
三、总结
本文详细介绍了 Spring Cloud Gateway 作为微服务统一入口的核心概念与实战技巧。从网关的背景价值出发,讲解了如何搭建基础环境、配置路由断言以及使用内置过滤器。重点剖析了自定义过滤器的实现机制与执行顺序,帮助开发者构建安全、高效且易于维护的网关层。在实际生产中,合理运用这些机制能有效提升系统的整体稳定性与可观测性。


