文章目录
- 前言
- 八大功能
- 网关配置文件中的三个核心配置
- 项目搭建
- 路由-规则配置
- 路由-工作原理
-
- 执行顺序
-
- [1.predicates: - Path=/**配置在最后,访问订单服务接口](#1.predicates: - Path=/**配置在最后,访问订单服务接口)
- [2.predicates: - Path=/**配置在最前,访问订单服务接口](#2.predicates: - Path=/**配置在最前,访问订单服务接口)
- 3.添加order属性值
- [断言 - predicates](#断言 - predicates)
- [过滤器 - Filter](#过滤器 - Filter)
- 跨域配置
- 微服务之间的调用经过网关吗?
前言
在分布式系统与微服务架构中,Gateway(网关)作为流量的 "入口管家",承担着连接客户端与后端服务的关键角色,负责请求的路由、过滤、协议转换、安全控制等核心功能。它解决了分布式系统中服务分散带来的统一接入、安全管控、流量治理等问题。
官网:https://docs.spring.io/spring-cloud-gateway/reference/
八大功能
1.统一入口
网关作为客户端访问后端所有服务的唯一接入点,替代后端服务集群中每个服务的独立暴露,将分散的服务入口收敛为单一地址。
- 简化客户端配置:客户端无需记忆后端多个服务的 IP / 域名,只需配置网关地址,降低对接复杂度。
- 屏蔽服务拓扑:隐藏后端服务的部署位置、集群结构(如服务扩容 / 缩容、节点迁移),客户端感知不到服务变化,实现 "服务透明化"。
- 统一流量管控:所有请求先经过网关,为后续的路由、认证、监控等功能提供 "前置拦截点",避免功能在每个服务中重复开发。
2.请求路由
网关根据预设规则(如 URL 路径、请求参数、请求头、客户端 IP 等),将客户端发送的请求精准转发到后端对应的服务实例(如将 /api/order/* 路由到订单服务,/api/goods/* 路由到商品服务)。
- 服务解耦:客户端无需关注后端服务的具体路由逻辑,服务拆分或重构时(如将 "用户服务" 拆分为 "用户认证服务" 和 "用户信息服务"),只需修改网关路由规则,无需改动客户端代码。
- 支持多种路由匹配:路由规则可以基于URL路径、HTTP方法(GET, POST等)、请求头(Header)、查询参数(Query Param)等进行匹配,转发到对应的服务。
- 动态路由:支持通过配置中心(如 Nacos、Apollo)实时更新路由规则,无需重启网关即可生效(例如:临时将部分用户的请求路由到新上线的测试服务,实现灰度发布)。
3.负载均衡
当后端一个服务部署多个实例时,网关按照负载均衡策略分发请求,避免单个实例过载。
常见负载均衡策略
- 轮询(Round Robin):请求按顺序轮流分配给每个实例。
- 加权轮询:为性能高的实例设置更高权重,分配更多请求。
- 最少连接数(Least Connections):请求优先转发给当前连接数最少的实例,适合请求耗时不均的场景。
- IP 哈希(IP Hash):根据客户端 IP 计算哈希值,固定转发到某个实例,保证会话粘滞。
4.流量控制
对进入后端服务的流量进行限流、熔断、降级 ,保护后端服务不被突发流量压垮。
限流
- 限制单位时间内的请求数(如每秒 1000 次),常用算法有令牌桶、漏桶。
- 令牌桶算法:固定速率产生令牌,请求需要消耗令牌
- 漏桶算法:请求以固定速率流出
- 可针对接口、用户、IP 维度限流,例如限制单个用户每秒最多 10 次请求。
熔断 - 当后端服务出现大量超时、错误时,网关暂时切断对该服务的请求转发,避免故障扩散。
降级 - 当流量超过阈值时,返回兜底数据(如 "服务繁忙,请稍后重试"),而非调用后端服务,保证核心功能可用。
5.身份认证
对所有进入网关的请求进行身份校验,拦截未授权请求,统一管控访问权限。
认证流程
- 客户端请求时携带认证凭证(如 Token、JWT、OAuth2.0 令牌)。
- 网关提取凭证并校验有效性(如校验 JWT 签名、查询用户权限列表)。
- 校验通过则转发请求;校验成功则网关通常会将用户身份信息放到请求头中,再转发给后端服务,校验失败则直接返回 401/403 错误,无需透传到后端服务。
将认证逻辑从各个微服务中抽离,统一实现,减少重复开发,降低维护成本。
6.协议转换
实现不同协议之间的转换,解决客户端与后端服务的协议不兼容问题。
常见协议转换场景
- HTTP/1.1 ↔ HTTP/2:网关支持 HTTP/2 接收客户端请求,再转换为 HTTP/1.1 调用不支持 HTTP/2 的后端服务。
- HTTP/HTTPS 转换:网关通常对外提供HTTPS服务,对内可以转发到使用HTTP的后端服务
- 非HTTP协议:一些高级网关支持将HTTP请求转换为其他协议,如:
- WebSocket:将HTTP升级请求转换为WebSocket连接,用于实时通信。
- gRPC:将HTTP/JSON请求转换为gRPC调用,与高性能的gRPC服务通信。
- 消息队列:将请求转换为消息发送到Kafka、RabbitMQ等。
后端服务可选择最适合自身的协议,无需适配客户端协议,提升服务灵活性。
7.系统监控
采集网关转发过程中的全链路监控数据,为系统运维和问题排查提供依据。
监控数据维度
- 流量指标:总请求数、QPS、响应时间(平均 / 最大 / 最小)、成功率。
- 错误指标:4xx/5xx 错误次数、错误率、具体错误原因。
- 链路追踪:记录请求从网关到后端服务的完整链路,关联每个环节的耗时,快速定位瓶颈(如集成 SkyWalking、Zipkin)。
- 日志采集:记录请求的源 IP、请求路径、参数、响应结果、转发目标服务等信息,支持审计和问题回溯。
8.安全防护
作为系统的 "第一道防线",拦截恶意请求,保护后端服务的安全。
核心防护手段
- 防 SQL 注入:检测请求参数中的 SQL 注入关键词,拦截恶意请求。
- 防 XSS 攻击:过滤请求中的脚本标签,防止跨站脚本攻击。
- 防 CSRF 攻击:校验请求中的 CSRF Token,防止跨站请求伪造。
- 黑白名单:基于 IP 或域名设置黑白名单,拦截黑名单中的请求,只允许白名单内的客户端访问。
- 敏感信息过滤:自动屏蔽响应中的敏感数据(如手机号、身份证号),避免信息泄露。
网关配置文件中的三个核心配置
- 路由 - Route
- 断言 - predicates
- 过滤器 - Filter

项目搭建

创建一个名为Gateway项目
依赖
xml
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</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-gateway</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>annotationProcessor</scope>
</dependency>
</dependencies>
配置文件
application.yml
yml
spring:
# profiles:
# include: route
application:
name: gateway
cloud:
nacos:
server-addr: 127.0.0.1:8848
server:
port: 80
启动类
java
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@EnableDiscoveryClient
@SpringBootApplication
public class GatewayMainApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayMainApplication.class, args);
}
}
启动后可在nacos服务列表中看到该网关服务。
路由-规则配置
基本的网关配置,通过网关访问服务。
新建配置文件application-route.yml
yml
spring:
cloud:
gateway:
routes: # 路由配置
- id: qf-service-order
uri: lb://qf-service-order
predicates:
- Path=/api/order/**
- id: qf-service-product
uri: lb://qf-service-product
predicates:
- Path=/api/product/**
注意:当前配置只支持直接将如Path后配置的接口名直接访问服务。
参数配置对应的类
org.springframework.cloud.gateway.route.RouteDefinition
java
@Validated
public class RouteDefinition {
private String id;
@NotEmpty
@Valid
private List<PredicateDefinition> predicates = new ArrayList<>();
@Valid
private List<FilterDefinition> filters = new ArrayList<>();
@NotNull
private URI uri;
private Map<String, Object> metadata = new HashMap<>();
private int order = 0;
...
}
需要将如订单服务的接口访问前缀和网关中配置的一样。@RequestMapping("/api/order")
java
@Slf4j
@RestController
@RequestMapping("/api/order")
public class OrderController {
...
}
启动服务后通过网关访问订单或商品服务,如:http://127.0.0.1/api/order/create?userId=112\&productId=22
路由-工作原理

执行顺序
1.predicates: - Path=/**配置在最后,访问订单服务接口
yml
spring:
cloud:
gateway:
routes: # 路由配置
- id: qf-service-order
uri: lb://qf-service-order
predicates:
- Path=/api/order/**
- id: qf-service-product
uri: lb://qf-service-product
predicates:
- Path=/api/product/**
- id: bing-route
uri: https://cn.bing.com/
predicates:
- Path=/**
发现可以正常访问订单服务接口。
2.predicates: - Path=/**配置在最前,访问订单服务接口
yml
spring:
cloud:
gateway:
routes: # 路由配置
- id: bing-route
uri: https://cn.bing.com/
predicates:
- Path=/**
- id: qf-service-order
uri: lb://qf-service-order
predicates:
- Path=/api/order/**
- id: qf-service-product
uri: lb://qf-service-product
predicates:
- Path=/api/product/**
发现跳转到bing搜索页面
3.添加order属性值
java
spring:
cloud:
gateway:
routes: # 路由配置
- id: bing-route
uri: https://cn.bing.com/
predicates:
- Path=/**
order: 10
- id: qf-service-order
uri: lb://qf-service-order
predicates:
- Path=/api/order/**
order: 1
- id: qf-service-product
uri: lb://qf-service-product
predicates:
- Path=/api/product/**
order: 2
如果配置文件中没有配置order,则默认从上到下,如果上面已经匹配到url了,则不会向下执行
断言 - predicates
长短写法
短写法

长写法

进入配置文件,点击spring.cloud.gateway.routes.predicates
java
@Validated
public class PredicateDefinition {
@NotNull
private String name;
private Map<String, String> args = new LinkedHashMap<>();
...
}
在刚刚的短写法中使用的是Path路径工厂,底层对应的PathRoutePredicateFactory
org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactory
java
public class PathRoutePredicateFactory extends AbstractRoutePredicateFactory<PathRoutePredicateFactory.Config> {
private static final Log log = LogFactory.getLog(PathRoutePredicateFactory.class);
private static final String MATCH_TRAILING_SLASH = "matchTrailingSlash";
private PathPatternParser pathPatternParser = new PathPatternParser();
public PathRoutePredicateFactory() {
//进入
super(Config.class);
}
...
}
org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactory.Config
java
@Validated
public static class Config {
private List<String> patterns = new ArrayList<>();
//如果设置为false,则配置的路径后 / 结尾时不会消去
private boolean matchTrailingSlash = true;
...
}
代码示例
java
spring:
cloud:
gateway:
routes: # 路由配置
- id: bing-route
uri: https://cn.bing.com/
predicates:
- Path=/**
order: 10
- id: qf-service-order
uri: lb://qf-service-order
# 写法1
# predicates:
# - Path=/api/order/**
# 写法2
predicates:
- name: Path
args:
patterns: /api/order/**
matchTrailingSlash: true
order: 1
- id: qf-service-product
uri: lb://qf-service-product
predicates:
- Path=/api/product/**
order: 2js
以下断言工厂实现类中去掉RoutePredicateFactory,剩下的前缀则为需要的名字(predicates.name)


使用Path和Query组合
效果:使用Path和Query组合,当访问/search请求路径携带q=haha时访问https://cn.bing.com/
配置了两个规则,则需要同时满足Path和Query的条件。
yml
spring:
cloud:
gateway:
routes: # 路由配置
- id: bing-route
uri: https://cn.bing.com/
# predicates:
# - Path=/**
predicates:
- name: Path
args:
patterns: /search
- name: Query
args:
param: q
regexp: haha
order: 10
- id: qf-service-order
uri: lb://qf-service-order
# 写法1
# predicates:
# - Path=/api/order/**
# 写法2
predicates:
- name: Path
args:
patterns: /api/order/**
matchTrailingSlash: true
order: 1
- id: qf-service-product
uri: lb://qf-service-product
predicates:
- Path=/api/product/**
order: 2
1.访问http://127.0.0.1/search,不会跳到到https://cn.bing.com/

2.访问http://127.0.0.1/search?q=aa,不会跳到到https://cn.bing.com/

3.访问http://127.0.0.1/search?q=haha,跳到到https://cn.bing.com/

自定义断言工厂
规则:只有用户为qf123时才可以访问
java
import jakarta.validation.constraints.NotEmpty;
import org.springframework.cloud.gateway.handler.predicate.AbstractRoutePredicateFactory;
import org.springframework.cloud.gateway.handler.predicate.GatewayPredicate;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.server.ServerWebExchange;
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
/**
* 自定义断言工厂
* 模仿QueryRoutePredicateFactory
* 注意配置文件中的name为当前自定义断言工厂的前缀Vip
*/
@Component
public class VipRoutePredicateFactory extends AbstractRoutePredicateFactory<VipRoutePredicateFactory.Config> {
/**
* 可以配置的参数
*/
@Validated
public static class Config {
@NotEmpty
private String param;
@NotEmpty
private String value;
public @NotEmpty String getParam() {
return param;
}
public void setParam(@NotEmpty String param) {
this.param = param;
}
public @NotEmpty String getValue() {
return value;
}
public void setValue(@NotEmpty String value) {
this.value = value;
}
}
public VipRoutePredicateFactory() {
super(Config.class);
}
/**
* 短写法时,参数的顺序
* @return
*/
@Override
public List<String> shortcutFieldOrder() {
return Arrays.asList("param", "value");
}
@Override
public Predicate<ServerWebExchange> apply(Config config) {
return new GatewayPredicate() {
@Override
public boolean test(ServerWebExchange serverWebExchange) {
// 当访问路径为 localhost/search?q=haha&user=qf123
ServerHttpRequest request = serverWebExchange.getRequest();
String first = request.getQueryParams().getFirst(config.param);
//如果路径有user参数,并且值等于qf123,则返回true
return StringUtils.hasText(first) && first.equals(config.value);
}
};
}
}
yml
spring:
cloud:
gateway:
routes: # 路由配置
- id: bing-route
uri: https://cn.bing.com/
# predicates:
# - Path=/**
predicates:
- name: Path
args:
patterns: /search
- name: Query
args:
param: q
regexp: haha
# - Vip=user,qf123
- name: Vip
args:
param: user
value: qf123
order: 10
- id: qf-service-order
uri: lb://qf-service-order
# 写法1
# predicates:
# - Path=/api/order/**
# 写法2
predicates:
- name: Path
args:
patterns: /api/order/**
matchTrailingSlash: true
order: 1
- id: qf-service-product
uri: lb://qf-service-product
predicates:
- Path=/api/product/**
order: 2
重启网关服务,可以看到无法访问之前的接口

http://127.0.0.1/search?q=haha\&user=qf123

http://127.0.0.1/search?q=haha\&user=aaa

可以看到只有user为qf123时才可以访问
过滤器 - Filter

路径重写

将需要转发的/api/order/** 改为 /**
yml
spring:
cloud:
gateway:
routes: # 路由配置
- id: bing-route
uri: https://cn.bing.com/
# predicates:
# - Path=/**
predicates:
- name: Path
args:
patterns: /search
- name: Query
args:
param: q
regexp: haha
# - Vip=user,qf123
- name: Vip
args:
param: user
value: qf123
order: 10
- id: qf-service-order
uri: lb://qf-service-order
# 写法1
# predicates:
# - Path=/api/order/**
# 写法2
predicates:
- name: Path
args:
patterns: /api/order/**
matchTrailingSlash: true
filters:
# 路径重写 例如,请求 /api/order/123 会被重写为 /123
- RewritePath=/api/order/?(?<segment>.*), /$\{segment}
order: 1
- id: qf-service-product
uri: lb://qf-service-product
predicates:
- Path=/api/product/**
order: 2
重启网关即可生效
http://127.0.0.1/api/order/create?userId=112\&productId=22
访问接口时返回指定的响应头
yml
spring:
cloud:
gateway:
routes: # 路由配置
- id: bing-route
uri: https://cn.bing.com/
# predicates:
# - Path=/**
predicates:
- name: Path
args:
patterns: /search
- name: Query
args:
param: q
regexp: haha
# - Vip=user,qf123
- name: Vip
args:
param: user
value: qf123
order: 10
- id: qf-service-order
uri: lb://qf-service-order
# 写法1
# predicates:
# - Path=/api/order/**
# 写法2
predicates:
- name: Path
args:
patterns: /api/order/**
matchTrailingSlash: true
filters:
# 路径重写 例如,请求 /api/order/123 会被重写为 /123
- RewritePath=/api/order/?(?<segment>.*), /$\{segment}
- AddResponseHeader=X-Response-Token, uuidtoken
order: 1
- id: qf-service-product
uri: lb://qf-service-product
predicates:
- Path=/api/product/**
order: 2

default-filters(类似全局filter)
yml
spring:
cloud:
gateway:
routes: # 路由配置
- id: bing-route
uri: https://cn.bing.com/
# predicates:
# - Path=/**
predicates:
- name: Path
args:
patterns: /search
- name: Query
args:
param: q
regexp: haha
# - Vip=user,qf123
- name: Vip
args:
param: user
value: qf123
order: 10
- id: qf-service-order
uri: lb://qf-service-order
# 写法1
# predicates:
# - Path=/api/order/**
# 写法2
predicates:
- name: Path
args:
patterns: /api/order/**
matchTrailingSlash: true
filters:
# 路径重写 例如,请求 /api/order/123 会被重写为 /123
- RewritePath=/api/order/?(?<segment>.*), /$\{segment}
# - AddResponseHeader=X-Response-Token, uuidtoken
order: 1
- id: qf-service-product
uri: lb://qf-service-product
predicates:
- Path=/api/product/**
order: 2
default-filters:
# 和断言工厂类似,使用前缀AddResponseHeaderGatewayFilterFactory
- AddResponseHeader=X-Response-Token, uuidtoken
重启网关服务,再次使用网关访问其他服务时,所有接口响应都会携带X-Response-Token:uuidtoken
GlobalFilter
java
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
@Component
@Slf4j
public class RtGlobalFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
ServerHttpResponse response = exchange.getResponse();
String uri = request.getURI().toString();
long start = System.currentTimeMillis();
log.info("请求【{}】开始:时间:{}",uri,start);
//========================以上是前置逻辑=========================
// 使用链式过滤器处理HTTP请求交换
Mono<Void> filter = chain.filter(exchange)
// 无论请求处理结果如何,都执行以下逻辑
.doFinally((result)->{
//=======================以下是后置逻辑=========================
long end = System.currentTimeMillis();
log.info("请求【{}】结束:时间:{},耗时:{}ms",uri,end,end-start);
});
return filter;
}
@Override
public int getOrder() {
return 0;
}
}
跨域配置
yml
spring:
cloud:
gateway:
globalcors:
cors-configurations:
'[/**]':
allowed-origin-patterns: '*'
allowed-headers: '*'
allowed-methods: '*'
routes: # 路由配置
- id: bing-route
uri: https://cn.bing.com/
# predicates:
# - Path=/**
predicates:
- name: Path
args:
patterns: /search
- name: Query
args:
param: q
regexp: haha
# - Vip=user,qf123
- name: Vip
args:
param: user
value: qf123
order: 10
- id: qf-service-order
uri: lb://qf-service-order
# 写法1
# predicates:
# - Path=/api/order/**
# 写法2
predicates:
- name: Path
args:
patterns: /api/order/**
matchTrailingSlash: true
filters:
# 路径重写 例如,请求 /api/order/123 会被重写为 /123
- RewritePath=/api/order/?(?<segment>.*), /$\{segment}
# - AddResponseHeader=X-Response-Token, uuidtoken
# 使用自定义过滤器生成jwt或uuid的一次性令牌
- OnceToken=X-Response-OneToken, jwt
order: 1
- id: qf-service-product
uri: lb://qf-service-product
predicates:
- Path=/api/product/**
order: 2
default-filters:
# 和断言工厂类似,使用前缀AddResponseHeaderGatewayFilterFactory
- AddResponseHeader=X-Response-Token, uuidtoken
访问接口

可以看到新增的跨域配置
微服务之间的调用经过网关吗?
一般不经过网关,但是可以在feign中配置经过网关
java
import com.qf.entity.Product;
import com.qf.feign.fallback.ProductFeignClientFallback;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
//填写需要远程调用的服务
@FeignClient(value = "qf-service-product", fallback = ProductFeignClientFallback.class) // feign客户端
public interface ProductFeignClient {
//mvc注解的两套使用逻辑
//1、标注在Controller上,是接受这样的请求
//2、标注在FeignClient上,是发送这样的请求
@GetMapping("/api/product/product/{id}")
Product getProductById(@PathVariable("id") Long id);
}
相关文章:
Spring Cloud Alibaba快速入门
Spring Cloud Alibaba快速入门-Nacos注册中心(上)
Spring Cloud Alibaba快速入门-Nacos注册中心(下)
Spring Cloud Alibaba快速入门-Nacos配置中心(上)
Spring Cloud Alibaba快速入门-Nacos配置中心(下)
Spring Cloud Alibaba快速入门-OpenFeign
Spring Cloud Alibaba快速入门-OpenFeign进阶用法
Spring Cloud Alibaba快速入门-Sentinel
Spring Cloud Alibaba快速入门-Sentinel流量控制(FlowRule)
Spring Cloud Alibaba快速入门-Sentinel熔断规则
Spring Cloud Alibaba快速入门-Sentinel热点参数限流