Spring Cloud Gateway 微服务网关核心原理与实战
一、网关概述
1.1 业务痛点
在微服务架构中,我们通常通过 Eureka 或 Nacos 解决服务注册与发现问题,利用 Spring Cloud LoadBalancer 处理负载均衡,并通过 OpenFeign 实现远程调用。然而,如果所有微服务的接口直接对外暴露,会带来显著的安全隐患。
为了保证安全性,服务端接口通常需要权限校验。但在微服务拆分后,原本单体应用中的多个模块变成了独立应用,导致我们需要在每个应用中重复实现校验逻辑。一旦策略调整,就需要修改多个服务,维护成本极高。
这就好比公司从单人办公发展到多部门协作:每个部门都要核实访客身份,效率低下且流程冗余。设立统一的前台(API 网关)进行身份核验,通过后各部门互信办理,是更优的解决方案。
1.2 核心概念
API 网关作为后端服务的唯一入口,类似于设计模式中的门面模式(Facade)。它充当整个微服务架构的总调度中心,所有外部客户端请求都必须经过它进行过滤和转发。
网关的核心功能包括:
- 权限控制:拦截非法请求,统一鉴权。
- 动态路由:根据规则将请求转发至具体微服务。
- 负载均衡:当目标服务有多个实例时自动分发流量。
- 限流保护:控制进入系统的流量,防止下游服务过载。
1.3 方案对比
业界成熟的网关方案众多,如 Nginx、Kong、Zuul 等。其中 Zuul 曾是 Spring Cloud Netflix 的核心组件,但随着 Netflix 停止部分组件的新特性开发,Spring Cloud Gateway 应运而生。
Spring Cloud Gateway 基于 Spring + SpringBoot 技术栈构建,旨在替代 Zuul。官方测试数据显示,其 RPS(每秒请求数)性能约为 Zuul 的 1.6 倍,更适合高并发场景。
二、Spring Cloud Gateway 实战
2.1 快速上手
搭建网关项目主要涉及依赖引入、启动类编写及路由配置三个步骤。
2.1.1 环境准备
首先创建一个新的 Spring Boot 项目,并引入以下核心依赖:
<!-- 网关核心依赖 -->
<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.2 启动类配置
标准的 Spring Boot 启动类即可,无需特殊注解。
@SpringBootApplication
public class GatewayApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayApplication.class, args);
}
}
2.1.3 路由配置
在 application.yml 中配置网关端口、服务名称及路由规则。这里以 Nacos 为注册中心为例:
server:
port: 10030
spring:
application:
name: gateway
cloud:
nacos:
discovery:
server-addr: 110.41.51.65:10020
gateway:
routes:
- id: product-service
uri: lb://product-service
predicates:
- Path=/product/**
- id: order-service
uri: lb://order-service
predicates:
- Path=/order/**
配置说明:
id:路由唯一标识。uri:目标服务地址,lb://表示从注册中心获取服务列表并进行负载均衡。predicates:断言条件,匹配 URL 路径前缀。
访问网关时,只需拼接路径即可,例如访问订单服务:http://127.0.0.1:10030/order/1。
2.2 路由断言工厂 (Route Predicate Factories)
Predicate 是 Java 8 的函数式接口,用于条件过滤。在 Gateway 中,它决定了请求是否匹配某个路由。
2.2.1 基础用法
默认提供了丰富的断言工厂,如 Path、After、Before 等。它们支持组合使用,例如同时限制路径和时间范围:
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]
这意味着只有 2026 年之后的请求才能访问 /product/** 路径。这种灵活性使得我们可以轻松实现灰度发布或定时任务控制。
2.3 过滤器工厂 (Gateway Filter Factories)
Predicate 负责决定路由,而 Filter 负责在路由前后执行额外逻辑。Filter 分为 Pre(前置)和 Post(后置)两种类型。
2.3.1 局部过滤器 (GatewayFilter)
适用于特定路由。例如,只为 product-service 添加请求参数:
filters:
- AddRequestParameter=userName, bite
这样,所有进入该路由的请求都会携带 userName=bite 参数。若需对所有路由生效,可使用 default-filters 配置全局默认过滤器。
2.3.2 全局过滤器 (GlobalFilter)\n作用于所有路由,常用于日志记录、监控指标或安全校验。Spring Cloud Gateway 内置了如 LoadBalancerClientFilter 等全局过滤器。
启用 Actuator 监控可观察内部过滤器链:
management:
endpoints:
web:
exposure:
include: "*"
访问 http://127.0.0.1:10030/actuator 即可查看网关运行状态。
2.4 过滤器执行顺序
当项目中同时存在 GatewayFilter 和 GlobalFilter 时,它们会被合并到一个过滤器链中排序执行。优先级由 order 值决定,数值越小优先级越高。
执行顺序遵循:defaultFilter > GatewayFilter > GlobalFilter。开发者可通过实现 Ordered 接口或添加 @Order 注解自定义优先级。
2.5 自定义过滤器
为了适配特定业务需求,我们可以扩展 Gateway 的过滤能力。
2.5.1 自定义 GatewayFilter
继承 AbstractGatewayFilterFactory 即可快速实现。注意 apply 方法中需返回一个 Mono<Void>,并在其中处理 Pre 和 Post 逻辑。
@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;
}
}
配合配置文件使用:
filters:
- name: Custom
args:
name: custom filter
2.5.2 自定义 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 凭借其高性能和灵活的扩展性,已成为微服务网关的首选方案。通过合理配置路由断言与过滤器,我们可以轻松构建统一的流量入口,实现鉴权、限流、监控等横切关注点。在实际开发中,建议优先使用内置过滤器,仅在必要时自定义,以保持系统的可维护性。


