Spring Cloud 微服务实战(四):每个请求都直连服务?你的集群缺一个 Gateway 门卫
Spring Cloud 微服务实战(四):每个请求都直连服务?你的集群缺一个 Gateway 门卫
个人主页:夏天拐跑了西瓜
专栏传送门:《大模型应用开发》、《Spring 生态全家桶体系化实战》
学习方向:Java 后端|AI‑Agent 大模型应用开发爱好者
⭐人生格言:路虽远,行则将至

本文是「Spring Cloud 微服务实战」系列的第四篇。网关是微服务集群的统一入口,所有外部请求都要经过它转发与过滤。本文先讲清楚网关的定位与 Gateway、Nginx、Zuul 的区别,再实战路由规则配置、
lb://负载均衡路由、常用断言与过滤器,最后手写一个全局过滤器实现统一的参数校验,帮你搭建一个安全可控的集群入口。
系列文章导航
- 《Spring Cloud 微服务实战(一):还在硬编码服务地址?Nacos 注册中心从零搭建》
- 《Spring Cloud 微服务实战(二):改个配置还要重启服务?Nacos 配置中心 + OpenFeign 实战》
- 《Spring Cloud 微服务实战(三):一个服务挂了,凭什么拖垮整个系统?Sentinel 限流熔断实战》
- 《Spring Cloud 微服务实战(四):每个请求都直连服务?你的集群缺一个 Gateway 门卫》(本篇)
一、Gateway
1.1 网关介绍
先明确网关的定位:它是所有后端服务的统一入口。外部请求要访问订单、库存或其他任何服务,都必须先经过网关,由网关转发到目标服务。

入口的安全策略做到位,后端服务的安全性就有了第一道保障。因此鉴权、限流、安全防护这类横切逻辑,通常都收敛在网关层统一处理。
网关的实现方案大致可以分为两类:
1、面向用户的网关:以 Nginx 为代表
- Nginx 的并发能力极强,用户请求先到达 Nginx,再由 Nginx 转发到后端服务;
- 但 Nginx 不属于 Spring Cloud 生态,与注册中心的整合成本较高,也难以用 Java 编写具体的业务逻辑。
2、后端入口网关:以 Spring Cloud Gateway 为代表(Netflix 开源的 Zuul 也属于此类)
- Gateway 的并发能力相对 Nginx 较弱,但它是 Spring Cloud 生态的原生组件,可以直接对接注册中心,基于服务名获取实例元数据;
- Gateway 还提供了丰富的 Filter 机制,可以在请求进入与响应返回的各个阶段插入自定义逻辑。
在展开 Gateway 之前,有必要了解一下它取代 Zuul 的原因。
Zuul 基于 Tomcat 容器,采用的是传统的 Servlet IO 模型:每进入一个请求,Web 服务就从线程池中分配一个线程进行处理。在并发不高时没有问题,但并发升高后会暴露两个缺陷:
- 每个线程都占用内存资源,高并发下线程数激增,内存消耗随之上涨;
- 线程过多时,大量 CPU 资源被消耗在线程上下文切换上。
因此在高并发场景下,网关不应该采用"一请求一线程"的传统 Servlet IO 模型。
针对这个问题,Gateway 选择了完全不同的技术路线。
Gateway 底层基于 Spring Framework 提供的 WebFlux 组件,用响应式模型替换了旧的 Servlet IO 模型:由少量线程(称为 Loop 线程)负责处理所有请求与响应的 IO 事件。
而具体的业务逻辑,则基于 WebFlux 使用的 Reactive Streams 异步编程模型处理。
处理请求的 Loop 线程对应 Reactor 模型中的 Reactor 线程;基于该模型实现的高性能通信框架代表是 Netty,此时 Reactor 线程即 Netty 中的 EventLoop 线程。
以上底层细节不必深究,只需理解结论:WebFlux 处理请求可以搭配 Netty 作为通信层。
Netty 提供了当前性能第一梯队的 IO 能力,再结合 Reactive Streams 的异步非阻塞处理,使得 Gateway 的性能远高于早期的 Zuul,并发能力更强。
补充:虽然 Zuul 新版本也切换到了基于 Netty 的 Reactor 模型,但 Spring Cloud 已停止对其维护,转而推出了自己的 Gateway,因此新项目直接选择 Gateway 即可。
建议:初学阶段不必深入 IO 模型、Netty 与异步编程的细节,等微服务整体落地后,再系统学习这些内容。
1.2 Gateway介绍
Gateway 作为网关,职责依然是请求的转发与过滤。其核心特点如下:
- 基于 Spring Framework 5、Project Reactor 和 Spring Boot 2.0 构建;
- 路由能够匹配请求携带的任何报文信息(请求头、参数、Cookie 等均可作为匹配条件);
- 谓词(Predicate)与过滤器(Filter)与具体路由绑定;
- 支持断路器集成(Hystrix / Sentinel);
- 集成 Spring Cloud DiscoveryClient,可直接对接 Nacos 等注册中心;
- 谓词与过滤器编写方式灵活,支持配置文件与 Java 代码两种方式;
- 内置请求限流过滤器;
- 支持路径重写,可在转发前与响应前修改各类报文。
此外,还需要了解 Gateway 的三个核心术语:
- Route(路由):网关的核心机制,由 ID、目标 URI、谓词集合与过滤器集合组成。当请求满足谓词匹配后,依次经过过滤器链,最终转发到目标 URI;
- Predicate(断言/谓词):用于匹配 HTTP 请求中携带的报文信息,可基于请求头、请求参数、Cookie 等多种条件作为匹配规则;
- Filter(过滤器):可在向下游发送请求之前或收到响应之后,对请求或响应进行修改。
下图是 Gateway 底层请求流转的整体过程:

整个流程涉及三个角色:客户端、Gateway、目标服务。
完整流转过程:
- 客户端请求发送到 Gateway;
- Gateway 基于 HandlerMapping 判断请求能否匹配到某条路由的谓词,若不匹配则返回 404;
- 匹配成功后,请求交给 Web Handler 处理,先经过过滤器链的前置过滤;
- 请求转发到目标服务,目标服务处理完成后将响应返回给 Gateway;
- 响应再经过过滤器链的后置过滤,最终返回给客户端。
1.3 Gateway初体验
1、先启动目标服务,确认其接口可以单独访问:

2、创建 gateway 工程。
3、导入依赖:
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<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>
</dependencies>
4、创建启动类:
@SpringBootApplication
@EnableDiscoveryClient
public class GatewayStarterApp {
public static void main(String[] args) {
SpringApplication.run(GatewayStarterApp.class, args);
}
}
5、编写配置文件,开启基于服务名的默认路由:
spring:
application:
name: gateway
cloud:
gateway:
discovery:
locator:
# 开启默认的路由规则,会根据注册中心中的服务名作为路径实现路由规则
enabled: true
server:
port: 80
6、测试效果:

以 http://localhost/order/order/info 为例,路径的三段含义如下:
http://localhost /order /order/info
- http://localhost: 访问的是 gateway 服务;
- /order: 路由的目标是订单服务;
- /order/info: 最终访问订单服务的 /order/info 接口。
1.4 自定义路由配置
自定义路由的本质是:基于断言定义请求进入后的匹配与转发规则。
1.4.1 yml方式
spring:
application:
name: gateway
cloud:
gateway:
discovery:
locator:
# 开启默认的路由规则,会根据注册中心中的服务名作为路径实现路由规则
enabled: false
routes:
- id: path_route
uri: http://localhost:9090/
predicates:
- Path=/order/**
# http://localhost/order/order/info 路由到 http://localhost:9090/order/order/info
# http://localhost/order/info 路由到 http://localhost:9090/order/info
1.4.2 配置类方式
除配置文件外,路由也可以通过 Java 配置类以编程方式定义:
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class GatewayRoutesConfig {
@Bean
public RouteLocator pathRoute(RouteLocatorBuilder routeLocatorBuilder) {
//1、基于routeLocatorBuilder获取构建route的Builder
RouteLocatorBuilder.Builder routes = routeLocatorBuilder.routes();
//2、设置route
return routes.route("path_route",route -> route.path("/order/**").uri("http://localhost:9090/")).build();
/*
# - id: path_route
# uri: http://localhost:9090/
# predicates:
# - Path=/order/**
*/
}
}
1.4.3 负载均衡
1.3 节中基于服务名的路由与负载均衡是默认路由机制自带的。使用自定义路由时,若需要从注册中心获取实例并实现负载均衡,只需将 uri 改为 lb://服务名 即可。
配置类写法:
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class GatewayRoutesConfig {
@Bean
public RouteLocator pathRoute(RouteLocatorBuilder routeLocatorBuilder) {
//1、基于routeLocatorBuilder获取构建route的Builder
RouteLocatorBuilder.Builder routes = routeLocatorBuilder.routes();
//2、设置route 将uri修改为lb://服务名即可
return routes.route("path_route",route -> route.path("/order/**").uri("lb://order")).build();
}
}
yml 写法:
spring:
cloud:
gateway:
routes:
- id: path_route
# 这个位置 ,lb代表负载均衡
uri: lb://order
predicates:
- Path=/order/**
1.5 断言
1.5.1 断言介绍
Gateway 内置了丰富的断言类型。每条路由可以配置多个断言,多个断言之间是"与"的关系——请求必须满足所有断言才会被路由到目标服务。
常用断言一览:
- After:只匹配指定时间之后的请求;
- Before:只匹配指定时间之前的请求;
- Between:只匹配指定时间范围内的请求;
- Cookie:请求携带的 Cookie 需匹配指定的正则表达式;
- Header:请求头需匹配指定的正则表达式;
- Host:匹配请求来源的主机(域名);
- Method:匹配请求方式(GET/POST 等);
- Path:匹配请求路径;
- Query:匹配请求参数;
- RemoteAddr:匹配请求来源的 IP 地址;
- Weight:按权重路由,参数为分组 group 与权重 weight,常用于灰度发布;
- XForWardedRemoteAddr:匹配请求头中的 X-Forwarded-For 或 RemoteAddr,识别经过代理的真实请求来源。
下面选取几个典型断言实测。
1.5.2 断言测试
After:只允许在指定时间之后的请求被路由:
spring:
cloud:
gateway:
routes:
- id: path_route
uri: lb://order
predicates:
- Path=/order/**
# - After=2025-05-16T19:30:25.789+08:00[Asia/Shanghai]
# - After=2026-05-16T19:30:25.789+08:00[Asia/Shanghai]
Header:请求头必须携带指定名称且值匹配正则:
spring:
cloud:
gateway:
routes:
- id: path_route
uri: lb://order
predicates:
- Path=/order/**
- Header=X-Request-Id, \d+
Method:限定请求方式:
spring:
cloud:
gateway:
routes:
- id: path_route
uri: lb://order
predicates:
- Path=/order/**
- Method=GET
其余断言的配置格式与此类似,参照官方文档即可举一反三。
1.6 Filter
Filter 作用于请求转发的前后阶段:请求到达 Gateway 并经断言匹配后,转发前后会依次经过过滤器链。
过滤器分为两部分:
- Gateway 内置过滤器:开箱即用,通过配置开启;
- 自定义过滤器:实现接口编写业务逻辑。
1.6.1 Gateway自带的Filter
Gateway 内置的过滤器数量较多,日常开发中以下四个最常用,掌握它们即可覆盖大部分场景。
1.6.1.1 AddRequestHeader
在请求转发到目标服务之前,追加一个请求头:
spring:
cloud:
gateway:
routes:
- id: path_route
uri: lb://order
predicates:
- Path=/order/**
filters:
- AddRequestHeader=X-Request-red, blue
1.6.1.2 AddRequestParameter
在请求转发到目标服务之前,追加一个请求参数:
spring:
cloud:
gateway:
routes:
- id: path_route
uri: lb://order
predicates:
- Path=/order/**
filters:
- AddRequestHeader=X-Request-red, blue
- AddRequestParameter=red, blue
1.6.1.3 AddResponseHeader
在响应返回给客户端之前,追加一个响应头:
spring:
cloud:
gateway:
routes:
- id: path_route
uri: lb://order
predicates:
- Path=/order/**
filters:
- AddRequestHeader=X-Request-red, blue
- AddRequestParameter=red, blue
- AddResponseHeader=X-Response-Red, Blue
1.6.1.4 StripPrefix
请求匹配断言后,转发前可截掉请求路径开头的 N 段前缀。常用于网关路径前缀与下游服务路径不一致的场景:
spring:
cloud:
gateway:
routes:
- id: path_route
uri: lb://order
predicates:
- Path=/order/**
filters:
- AddRequestHeader=X-Request-red, blue
- AddRequestParameter=red, blue
- AddResponseHeader=X-Response-Red, Blue
- StripPrefix=1
# http://localhost/order/order/info 路由到 http://localhost:9090/order/info
# http://localhost/order/info 路由到 http://localhost:9090/info
1.6.1.5 DefaultFilter
前面介绍的过滤器都作用于单条路由。如果某些过滤器需要对所有路由统一生效,可以使用 default-filters 配置:
spring:
cloud:
gateway:
default-filters:
- AddRequestHeader=X-Request-red, blue
- AddRequestParameter=red, blue
- AddResponseHeader=X-Response-Red, Blue
- StripPrefix=1
1.6.2 自定义过滤器
当内置过滤器无法满足需求时,可以自定义过滤器。实现方式很简单:创建一个类实现对应接口,重写方法并加入业务逻辑即可。
需要实现两个接口:
- GlobalFilter:重写 filter 方法,通过 exchange 可以获取请求报文与响应报文的信息,在方法内部可完成限流、鉴权等操作:
- 返回
exchange.getResponse().setComplete():拦截请求; - 返回
chain.filter(exchange):放行请求。
- 返回
- Ordered:指定多个过滤器之间的执行顺序,返回值越小,优先级越高。
下面实现一个参数校验过滤器:要求所有请求必须携带 key 参数且值非空,否则返回 400。
package com.study.filters;
import com.alibaba.nacos.common.utils.StringUtils;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
/**
* 实现Gateway的自定义过滤器,并且实现参数校验。
*/
@Component
public class ParameterInvalidateFilter implements GlobalFilter, Ordered {
// 要求必须传递一个参数, key=value, 要求value不允许为空,也不允许为空串,否则400的错误
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// 具体的逻辑在这些。
String value = exchange.getRequest().getQueryParams().getFirst("key");
// 判断
if(StringUtils.isEmpty(value)){
System.out.println("参数异常!!!");
exchange.getResponse().setStatusCode(HttpStatus.BAD_REQUEST);
// 拦截住,直接不往下走Filter了。
return exchange.getResponse().setComplete();
}
return chain.filter(exchange);
}
@Override
// 返回的数值越小,优先级越高。
public int getOrder() {
return 0;
}
}
二、总结
本文讲解了微服务集群的统一入口 Gateway,核心收获如下:
- Gateway 基于 WebFlux + Netty 的异步模型,相比 Zuul 的传统 Servlet 模型并发能力更强。
- 掌握 Route、Predicate、Filter 三大核心概念及请求在 Gateway 内的完整流转流程。
- 路由规则支持 yml 与配置类两种配置方式,
lb://服务名即可对接注册中心实现负载均衡路由。 - 熟悉 Path、Method、Header、After 等常用断言,以及 AddRequestHeader、AddRequestParameter、AddResponseHeader、StripPrefix、DefaultFilter 等常用过滤器。
- 通过实现 GlobalFilter + Ordered 自定义全局过滤器,统一完成鉴权、参数校验等入口逻辑。
至此,Spring Cloud 微服务链路的核心组件(注册发现、配置中心、远程调用、限流熔断、网关)已全部讲解完毕,后续可以自行扩展链路追踪(Sleuth + Zipkin)与 DevOps 自动化部署等内容。
感兴趣的同学记得 点赞 + 关注,第一时间获取更新通知!
更多推荐

所有评论(0)