目录
- 概述
- 工作流程
- 入门配置
- 路由映射
- GateWay高级特性
-
- Route 以服务名动态获取服务uri
- Predicate断言(谓词)
-
- The After Route Predicate Factory
- The Before Route Predicate Factory
- The Between Route Predicate Factory
- The Cookie Route Predicate Factory
- The Header Route Predicate Factory
- The Host Route Predicate Factory
- The Method Route Predicate Factory
- The Path Route Predicate Factory
- The Query Route Predicate Factory
- The RemoteAddr Route Predicate Factory
- The Weight Route Predicate Factory
- The XForwarded Remote Addr Route Predicate Factory
- 自定义断言
- Filter 过滤
- 相关文献
概述
Gateway是在Spring生态系统之上构建的API网关服务,基于Spring6,Spring Boot 3和Project Reactor等技术。它旨在为微服务架构提供一种简单有效的统一的 API 路由管理方式,并为它们提供跨领域的关注点,例如:安全性、监控/度量和恢复能力。
在Spring Cloud中,在1.x版本中都是采用的Zuul网关;
但在2.x版本中,zuul的升级一直跳票,SpringCloud最后自己研发了一个网关SpringCloud Gateway替代Zuul
微服务架构网关位置图如下:
作用
- 反向代理
- 鉴权
- 流量控制
- 熔断
- 日志监控
总结:
Spring Cloud Gateway组件的核心是一系列的过滤器,通过这些过滤器可以将客户端发送的请求转发(路由)到对应的微服务。
Spring Cloud Gateway是加在整个微服务最前沿的防火墙和代理器,隐藏微服务结点IP端口信息,从而加强安全保护。
Spring Cloud Gateway本身也是一个微服务,需要注册进服务注册中心(像consul)。
GateWay三大核心
- Route-路由
网关的基本构建块。它由 ID、目标 URI、谓词集合和筛选器集合定义。如果聚合谓词为 true,则匹配路由。 - Predicate-断言
这是一个 Java 8 函数谓词。输入类型是 Spring Framework ServerWebExchange 这使您可以匹配 HTTP 请求中的任何内容,例如标头或参数,如果请求和断言相匹配则进行路由。 - Filter-过滤器
这些是使用特定工厂构建的 GatewayFilter 实例。在这里,您可以在发送下游请求之前或之后修改请求和响应。
application.yml配置示例
GateWay有两种配置展现形式,Shortcut Configuration(快捷方式配置)、Fully Expanded Arguments(完全展开的参数)
Shortcut Configuration:
spring:
cloud:
gateway:
routes:
- id: after_route #我们自定义的路由 ID,保持唯一
uri: https://example.org #目标服务地址
predicates: #路由条件,Predicate接受一个输入参数返回一个布尔值。
- Cookie=mycookie,mycookievalue #该属性包含多种默认方法来将Predicate组合成其他复杂的逻辑(比如:与,或,非)
Fully Expanded Arguments:
spring:
cloud:
gateway:
routes:
- id: after_route
uri: https://example.org
predicates:
- name: Cookie
args:
name: mycookie
regexp: mycookievalue
图理解
如下图
web前端请求,通过一些匹配条件,定位到真正的服务节点。并在这个转发过程的前后,进行一些精细化控制。
predicate就是我们的匹配条件;
filter,就可以理解为一个无所不能的过滤器。有了这两个元素,再加上目标uri,就可以实现一个具体的路由了
举个例子:
我要去华为专卖店买手机,那么我肯定不能去苹果专卖店去,那么这个去哪个店就是路由,我到了华为专卖店,我要买华为黑色的mate60pro,店里有黑色、白色的,刚好有我想要的黑色,那么颜色匹配上我想要的,这个判断就是断言,如果没有匹配上,那我就买不了,我买上了心爱的手机,这时候专卖店给我送了个屏幕膜,这时候给我贴上了给我,举动非常贴心,在我买手机后给我在裸机上贴了个膜,这就是过滤器的post动作。
工作流程
客户端向 Spring Cloud Gateway 发出请求。然后在 Gateway Handler Mapping 中找到与请求相匹配的路由,将其发送到 Gateway Web Handler。Handler 再通过指定的过滤器链来将请求发送到我们实际的服务执行业务逻辑,然后返回。
过滤器之间用虚线分开是因为过滤器可能会在发送代理请求之前(Pre)或之后(Post)执行业务逻辑。
在“pre”类型的过滤器可以做参数校验、权限校验、流量监控、日志输出、协议转换等;
在“post”类型的过滤器中可以做响应内容、响应头的修改,日志的输出,流量监控等有着非常重要的作用。
核心逻辑就是:路由转发+断言判断+执行过滤器链
入门配置
网关依赖引入:
<!--gateway-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
将网关服务注册进去(只提供思路,具体代码实现可参考其他文章 ,关键词:consul服务注册)
路由映射
诉求:不想暴露真实的ip地址、服务名等等给外部使用,在外面套一层网关
新起一个服务要求访问:http://localhost:8001/pay/gateway/get/1,http://localhost:8001/pay/gateway/info,可通
网关服务yml新增配置:
然后重启网关服务。
如网关yml配置正确,则访问http://localhost:9527/pay/gateway/get/1,http://localhost:9527/pay/gateway/info可通,这样就达到了,外部服务只需要知道9527端口,不知实际8001真实端口的要求。
GateWay高级特性
Route 以服务名动态获取服务uri
上面的例子很简单,但是问题也来了,一个服务简单的写写ip端口没问题,如果是部署集群呢,会很麻
怎么解决呢?
网关yml修改前:
网关yml修改后:通过lb后面跟着服务名,这样就能不用关心服务的ip端口了
Predicate断言(谓词)
Spring Cloud Gateway 将路由作为 Spring WebFlux HandlerMapping 基础结构的一部分进行匹配。Spring Cloud Gateway 包含许多内置的路由谓词工厂。所有这些谓词都与 HTTP 请求的不同属性匹配。您可以将多个路由谓词工厂与逻辑 and 语句组合在一起。以下图右侧是内置的断言。
The After Route Predicate Factory
After 路由谓词工厂采用一个参数 a datetime (即 java ZonedDateTime )。此谓词匹配在指定日期时间之后发生的请求。以下示例配置路由后谓词:
spring:
cloud:
gateway:
routes:
- id: after_route
uri: https://example.org
predicates:
- After=2017-01-20T17:42:47.789-07:00[America/Denver]
案例说明:只能通过2017 年 1 月 20 日 17:42 Mountain Time (Denver) 之后的请求
After、Before、Between 时间参数获取方式:
ZonedDateTime zbj = ZonedDateTime.now(); // 默认时区
The Before Route Predicate Factory
Before 路由谓词工厂采用一个参数 a datetime (即 java ZonedDateTime )。此谓词匹配在指定的 datetime .以下示例配置 before route 谓词:
spring:
cloud:
gateway:
routes:
- id: before_route
uri: https://example.org
predicates:
- Before=2017-01-20T17:42:47.789-07:00[America/Denver]
案例说明:只能通过 2017 年 1 月 20 日 17:42 Mountain Time (Denver) 之前的请求
The Between Route Predicate Factory
Between 路由谓词工厂采用两个参数, datetime1 datetime2 它们是 java ZonedDateTime 对象。此谓词匹配在 datetime1 之后和之前 datetime2 发生的请求。该 datetime2 参数必须位于 datetime1 之后。以下示例配置 between route 谓词:
spring:
cloud:
gateway:
routes:
- id: between_route
uri: https://example.org
predicates:
- Between=2017-01-20T17:42:47.789-07:00[America/Denver], 2017-01-21T17:42:47.789-07:00[America/Denver]
案例说明:只能通过2017 年 1 月 20 日 17:42 山地时间(丹佛)之后和 2017 年 1 月 21 日 17:42 山地时间(丹佛)之前的请求
时间的之前、之后、中间,很符合现在活动业务中的秒杀业务。
The Cookie Route Predicate Factory
Cookie 路由谓词工厂采用两个参数,cookie name 和 a regexp (Java 正则表达式)。此谓词匹配具有给定名称且其值与正则表达式匹配的 cookie。以下示例配置 cookie 路由谓词工厂:
spring:
cloud:
gateway:
routes:
- id: cookie_route
uri: https://example.org
predicates:
- Cookie=chocolate, ch.p
案例说明: