[spring cloud] gateway网关
·
Spring Cloud Gateway 是微服务架构的门面 (Facade)。它是所有外部请求进入内部微服务集群的唯一入口。
作用包含:请求路由,负载均衡,流量控制等
在 Spring Cloud Alibaba 体系中,它的地位相当于公司的前台:
- 路由 (Router):客人找谁?(转发请求)
- 断言 (Predicate):能不能进?(匹配条件)
- 过滤器 (Filter):进门前/出门后要做什么?(鉴权、日志、限流)
核心注意点:Spring Cloud Gateway 基于 WebFlux (Netty) 响应式编程,千万不要引入 spring-boot-starter-web(Tomcat),否则会启动报错!
1. 核心模型:路由、断言、过滤器
这三者组成了 Gateway 的核心工作流程:
- Route (路由):构建网关的基本模块。它由 ID、目标 URI、一组断言和一组过滤器组成。
- Predicate (断言):Java 8 的
Predicate。匹配 HTTP 请求的所有内容(如路径、Header、时间)。匹配成功,才执行路由。 - Filter (过滤器):在请求被路由前(Pre)和路由后(Post)对请求进行修改。


2. 基础配置实战 (YAML)
假设我们要把访问 http://gateway-host/order/** 的请求转发给 Nacos 里的 service-order 服务。
pom.xml 依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<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>
application.yml 配置:
server:
port: 9000
spring:
application:
name: api-gateway
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
gateway:
routes:
- id: route_order # 1. 路由 ID,保持唯一
# 2. 目标 URI
# lb:// 代表 LoadBalance,从 Nacos 拉取 service-order 的列表并负载均衡
uri: lb://service-order
# 3. 断言 (Predicates):判断条件
predicates:
- Path=/order/** # 路径匹配
- After=2026-01-01T00:00:00.000+08:00[Asia/Shanghai] # 时间匹配(要在2026年之后)
# - Header=X-Request-Id, \d+ # 正则匹配 Header
# 4. 过滤器 (Filters):针对这个路由的局部处理
filters:
- StripPrefix=1 # 去掉路径的第一层 ( /order/create -> /create )
- AddRequestHeader=X-From, Gateway # 给下游服务加个头
3. 全局过滤器 (GlobalFilter) —— Java 代码实战
这是开发中最常用的功能。不同于 YAML 里配置的局部过滤器,全局过滤器对所有路由生效。
场景:统一鉴权。如果请求头里没有 Authorization,直接拦截,不让访问下游微服务。
代码编写 (GlobalAuthFilter.java):
package com.example.gateway.filter;
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.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
public class GlobalAuthFilter implements GlobalFilter, Ordered {
/**
* 过滤逻辑
* Exchange: 交换机,包含 Request 和 Response (注意是 Reactive 的,不是 HttpServletRequest)
* Chain: 过滤器链
*/
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
// 1. 获取请求参数或 Header 中的 token
String token = request.getHeaders().getFirst("Authorization");
// 2. 校验逻辑 (这里简单模拟:没有 token 就拦截)
if (token == null || token.isEmpty()) {
// 设置响应状态码为 401 未授权
ServerHttpResponse response = exchange.getResponse();
response.setStatusCode(HttpStatus.UNAUTHORIZED);
// 3. 终止请求,直接返回
return response.setComplete();
}
// 4. 放行,进入下一个过滤器
return chain.filter(exchange);
}
/**
* 过滤器优先级,数字越小越先执行
*/
@Override
public int getOrder() {
return -1;
}
}
4. 全局跨域配置 (Global CORS)
前后端分离项目中,前端(比如 Vue 跑在 8080)访问网关(跑在 9000),浏览器会报 CORS 跨域错误。
在 Gateway 中,不需要写 Java 配置类,直接在 YAML 解决最简单。
application.yml 追加:
spring:
cloud:
gateway:
globalcors: # 全局跨域配置
add-to-simple-url-handler-mapping: true # 解决 options 请求被拦截问题
cors-configurations:
'[/**]': # 拦截所有请求
allowedOrigins: # 允许哪些网站跨域
- "http://localhost:8080"
- "https://www.example.com"
allowedMethods: # 允许的方法
- GET
- POST
- PUT
- DELETE
- OPTIONS
allowedHeaders: "*" # 允许的头
allowCredentials: true # 是否允许携带 cookie
maxAge: 360000 # 跨域检测有效期
5. 总结:Gateway 知识全景图
| 模块 | 核心关键字 | 作用 | 实战重点 |
|---|---|---|---|
| 基础 | WebFlux / Netty | 异步非阻塞高性能网关 | 严禁引入 spring-boot-starter-web |
| 路由 | uri: lb://xxx |
请求转发 + 负载均衡 | 配合 Nacos 使用 |
| 断言 | Predicates |
匹配规则 (Path, Time, Header) | 最常用的是 Path=/xxx/** |
| 过滤器 | Filters / GlobalFilter |
请求鉴权、日志、修改参数 | 实现 GlobalFilter 接口做统一拦截 |
| 跨域 | globalcors |
解决浏览器同源策略限制 | YAML 配置即可,无需 Java 代码 |
Gateway 是整个微服务最外层的“壳”。
- 安全:通常在这里做 JWT 解析和验签。
- 限流:Gateway 可以整合 Sentinel,针对某个路由(Route)或者某个 API 分组进行限流。如果网关被冲垮,后面所有服务都完了,所以网关流控是重中之重。
更多推荐




所有评论(0)