org.springframework.cloud.gateway 是 Spring Cloud 生态系统中的一个新一代的、功能强大的 API 网关。
1. 什么是 API 网关 (API Gateway)?
在讲解 Spring Cloud Gateway 之前,我们先要理解它扮演的角色------API 网关。
在一个微服务架构中,系统被拆分成多个独立的服务(如用户服务、商品服务、订单服务等)。客户端(如网页、手机 App)如果直接和这些服务通信,会面临很多问题:
-
地址管理复杂:客户端需要知道所有服务的网络地址。
-
认证授权繁琐:每个服务都需要独立做用户认证。
-
跨域问题:浏览器访问不同域的服务会产生跨域问题。
-
协议转换困难:如果有的服务用 HTTP,有的用 WebSocket,客户端处理起来很麻烦。
API 网关就是为了解决这些问题而诞生的。它像一个"大门"或"前台接待",统一接收所有外部请求,然后根据一定的规则,将请求转发到内部对应的微服务上。
网关的核心职责包括:
-
路由 (Routing):将请求转发到正确的微服务。
-
认证与安全 (Authentication & Security):统一处理身份验证、权限控制。
-
负载均衡 (Load Balancing):将请求分发到服务的多个实例上。
-
限流熔断 (Rate Limiting & Circuit Breaking):防止流量过大冲垮后端服务。
-
日志监控 (Logging & Monitoring):记录请求日志,监控系统健康状况。
-
协议转换:如 HTTP 到 gRPC 的转换。
2. Spring Cloud Gateway 详解
org.springframework.cloud.gateway 就是 Spring 官方推出的用于构建 API 网关的框架。它是对之前 Netflix Zuul 1.x 的替代和升级。
核心特性
-
基于响应式编程模型 :它构建于 Spring Framework 5, Project Reactor 和 Spring Boot 2之上,底层网络通信使用的是 Netty 。这使得它是一个完全异步、非阻塞的网关。相比于 Zuul 1.x 的阻塞式 I/O 模型,Gateway 在高并发场景下性能更好,资源消耗更低。
-
动态路由:可以与服务发现组件(如 Eureka, Consul, Nacos)无缝集成,动态地从注册中心获取服务地址并创建路由,无需重启网关。
-
强大的断言(Predicate)和过滤器(Filter):这是 Gateway 的核心。你可以通过非常灵活的方式来定义路由规则和请求处理逻辑。
-
易于配置:支持通过配置文件(如 application.yml)或 Java Bean 的方式进行配置。
-
高集成度:与 Spring Cloud 生态的其他组件(如 Spring Security, Resilience4j)可以很好地集成,轻松实现安全、熔断等功能。
-
支持 Websockets。
3. 三大核心概念
Spring Cloud Gateway 的工作原理基于三个核心概念:路由 (Route) 、断言 (Predicate) 和 过滤器 (Filter)。
a. 路由 (Route)
路由是网关最基本的组成单元。它由以下几个部分构成:
-
ID: 路由的唯一标识。
-
目标 URI: 请求最终被转发到的目标地址。
-
一组断言 (Predicates): 决定一个请求是否匹配该路由的条件。
-
一组过滤器 (Filters): 在请求被转发前后对其进行修改或处理。
b. 断言 (Predicate)
断言就是一个布尔值判断,输入是 ServerWebExchange(包含了 HTTP 请求的所有信息),输出是 true 或 false。如果一个请求满足了某个路由的所有断言条件,那么这个请求就会被该路由处理。
Spring Cloud Gateway 内置了多种断言工厂,可以让你根据请求的各种属性来匹配路由:
-
Path: 根据请求的 URL 路径进行匹配。例如 Path=/users/**。
-
Method: 根据请求的方法进行匹配。例如 Method=GET。
-
Header: 根据请求头进行匹配。例如 Header=X-Request-Id, \d+。
-
Query: 根据请求参数进行匹配。例如 Query=name, john。
-
Host: 根据主机名进行匹配。例如 Host=**.somehost.org。
-
Cookie: 根据 Cookie 进行匹配。
-
After/Before/Between: 根据时间进行匹配。
多个断言可以组合使用,它们之间是"与"(AND)的关系。
c. 过滤器 (Filter)
过滤器用于在请求被路由之前或之后,对请求和响应进行修改。过滤器分为两种类型:
-
GatewayFilter: 作用于单个路由。
-
GlobalFilter: 全局过滤器,作用于所有路由。
过滤器的生命周期分为 "pre" 和 "post" 两个阶段:
-
Pre-filtering : 在请求被转发到下游服务之前执行。可以用来添加请求头、记录日志、进行权限验证等。
-
Post-filtering : 在下游服务返回响应之后执行。可以用来修改响应体、添加响应头等。
常见的内置过滤器有:
-
AddRequestHeader, AddResponseHeader: 添加请求/响应头。
-
RewritePath: 重写请求路径。
-
Retry: 失败重试。
-
RateLimiter: 请求限流。
-
CircuitBreaker: 熔断器。
4. 工作流程
一个请求进入 Spring Cloud Gateway 的完整流程如下:
-
客户端向 Gateway 发送请求。
-
Gateway 的 Handler Mapping 模块接收请求,并根据一系列的断言 (Predicates) 来寻找匹配的路由 (Route)。
-
一旦找到匹配的路由,请求就会被发送给 Gateway 的 Web Handler。
-
Web Handler 会将请求通过一个过滤器链 (Filter Chain)。
-
在 "pre" 阶段,请求会依次经过所有全局过滤器 (GlobalFilters) 和该路由配置的网关过滤器 (GatewayFilters)。
-
过滤器链执行完毕后,Gateway 发出代理请求,通过负载均衡(如 lb:// 协议)将请求转发到真正的后端微服务。
-
微服务处理请求并返回响应。
-
响应会再次经过过滤器链的 "post" 阶段,倒序执行所有过滤器。
-
最终,Gateway 将处理后的响应返回给客户端。
5. 配置示例
下面是一个典型的 application.yml 配置,它展示了如何定义路由:
spring:
cloud:
gateway:
# 开启与服务发现组件的集成
discovery:
locator:
enabled: true
lower-case-service-id: true # 将服务名转为小写
# 定义路由规则
routes:
# 路由1:访问 /user/** 的请求会被转发到 user-service
- id: user_service_route # 路由的唯一ID
uri: lb://user-service # 目标URI,lb:// 表示从服务发现中获取地址
predicates: # 断言条件
- Path=/user/**
filters: # 过滤器
# 重写路径,例如 /user/1 -> /1
- RewritePath=/user/(?<segment>.*), /$\{segment}
# 路由2:访问 /product/** 的请求会被转发到 product-service
- id: product_service_route
uri: lb://product-service
predicates:
- Path=/product/**
content_copydownload
Use code with caution.Yaml
解释:
-
id: 路由的唯一标识,方便管理。
-
uri: lb://user-service: lb 是 load-balancer 的缩写,表示 Gateway 会从服务注册中心(如 Nacos、Eureka)查找名为 user-service 的服务,并对其进行负载均衡。
-
predicates: - Path=/user/**: 当请求的路径匹配 /user/ 开头的模式时,该路由生效。
-
filters: - RewritePath...: 这是一个过滤器,它会重写请求路径。例如,当客户端请求 http://gateway-host/user/profile/1 时,Gateway 会将请求路径修改为 /profile/1,然后再转发给 user-service。
6. 总结:为什么要用 Spring Cloud Gateway?
-
性能优越:基于非阻塞模型,适合处理高并发 I/O 密集型任务。
-
功能强大:提供了丰富的路由、断言和过滤器,能满足绝大多数网关场景的需求。
-
与 Spring Cloud 生态无缝集成:是目前构建 Spring Cloud 微服务架构的首选网关。
-
易于开发和扩展:可以轻松编写自定义的过滤器和断言,实现复杂的业务逻辑。
总而言之,org.springframework.cloud.gateway 是一个现代、高效、功能完备的 API 网关解决方案,是 Spring Cloud 微服务技术栈中不可或缺的一环。