系列学习 Gateway 之第 2 篇 —— 路由规则 predicate,动态路由配置

本文详细介绍了Spring Cloud Gateway的各种路由规则,包括Path、Query、Method、datetime、RemoteAddr和Header等Predicate的使用,以及如何实现动态路由,如通过服务名称从注册中心获取服务地址和结合服务发现进行路由。此外,还展示了如何配置After datetime路由以过滤特定时间后的请求,以及RemoteAddr Predicate来限制特定IP地址的访问。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本篇博客基于:https://blog.csdn.net/BiandanLoveyou/article/details/117323743

路由规则 predicate 也叫谓词,这些Predict的源码在org.springframework.cloud.gateway.handler.predicate 包中,列举各种 predicate :

在上图中,有很多类型的 predicate。比如说时间类型的 Predicated(AfterRoutePredicateFactory BeforeRoutePredicateFactory BetweenRoutePredicateFactory),当只有满足特定时间要求的请求会进入到此 predicate 中,并交由 router 处理;cookie类型的CookieRoutePredicateFactory,指定的 cookie 满足正则匹配,才会进入此 router。以及 host、method、path、querparam、remoteaddr 类型的 predicate,每一种 predicate 都会对当前的客户端请求进行判断,是否满足当前的要求,如果满足则交给当前请求处理。如果有很多个 Predicate,并且一个请求满足多个Predicate,则按照配置的顺序第一个生效。

路由规则之 Path

OK,上一篇博客已经讲解了 Gateway 的入门,并且展示了路由规则里的 Path(请求路径正则表达式匹配指定值)。博客地址:https://blog.csdn.net/BiandanLoveyou/article/details/117323743

spring:
  application:
    name: gateway-server
  cloud:
    gateway:
      routes:
        # 路由的 ID,没有固定规则但要求唯一,建议配合服务名
        # 产品微服务路由
      - id: product-server
        # 匹配后提供服务的路由地址
        uri: http://${eureka.instance.hostname}:9090/
        # 断言,路径相匹配的进行路由,配置服务端的方法路径
        predicates:
          - Path=/product/**

为了快速学习,这里只展示 predicates 的配置部分,其它的配置跟 Path 的一致。

 

路由规则之 Query

Query 路由有2个参数:一个参数名和一个参数值的正则表达式(非必选)。

- Query=token,get.*

在上面的配置文件中,配置了请求中含有参数 token,并且 token 的值匹配 get  开头,则请求命中路由,能够被正确路由转发。如访问:http://127.0.0.1:9999/product/1?token=getName

 

路由规则之 Method

- Method=GET

在上面的配置中,所有的 GET 类型的请求都会路由转发到配置的 uri。

如访问:http://127.0.0.1:9999/product/1

但是 POST 请求是无法被路由的。

 

路由规则之 datetime

datetime 有3种:After、Before、Between。这里讲解 After。

- After=2021-05-28T08:08:08+08:00[Asia/Shanghai]

当请求的时间在这个配置的时间之后,请求会被路由到对应的 URI 上。

 

路由规则之 RemoteAddr

- RemoteAddr=192.168.0.104/0   # 匹配192.168.0.104地址,0表示子网掩码

这是远程地址的匹配规则,只有匹配到了该 IP 地址,才会被路由。

 

路由规则之 Header

- Header=X-Request-Id, \d+

 在上面的配置中,当请求的Header中有 X-Request-Id 的header名,且 header 值为数字时,请求会被路由到配置的 uri。

使用 postman 发送请求:

 

Gateway 动态路由

在实际开发过程中,我们都是使用动态路由比较多,上面讲述的几种路由,只是小打小闹而已,实际项目中很少用到,比如我们后期要修改什么路由规则,难道要修改代码,重新发布版本?

1、动态获取 URI

我们修改 Gateway 的配置文件

spring:
  application:
    name: gateway-server
  cloud:
    gateway:
      routes:
        # 路由的 ID,没有固定规则但要求唯一,建议配合服务名
        # 产品微服务路由
      - id: product-server
        # 根据服务名称从注册中心获取服务地址
        uri: lb://product-server
        # 断言
        predicates:
          - Path=/product/**

注意到 uri 的配置: lb://product-server    ,其中,lb 表示 loadbalance 负载均衡的缩写。会根据服务名称从注册中心获取服务地址。

这种方式也不够好,在实际开发中,如果增加、删除某个微服务,还是要修改代码,重新发布版本。

 

2、服务名称转发

spring:
  application:
    name: gateway-server
  cloud:
    gateway:
      discovery:
        locator:
          # 是否与注册中心进行结合,通过服务ID转发到具体的服务实例
          enabled: true  #是否开启基于服务发现的路由规则
          lower-case-service-id: true  #是否将服务名称转为小写
          

这里我们配置 discovery,让 Gateway 与注册中心结合,通过服务ID去转发到具体的服务中。

重启 Gateway 服务,这时候我们如果想访问产品微服务,就要输入网关地址 + 产品微服务的服务名称:http://127.0.0.1:9999/product-server/product/1

想访问订单微服务,就要输入网关地址 + 订单微服务的名称:

http://127.0.0.1:9999/order-server/order/1

 

OK,Gateway 路由配置讲解到这。

<think>好的,我现在需要为用户解析Spring Cloud Gateway中的RouteDefinitionRepository存储器。首先,我需要回忆一下Spring Cloud Gateway的基本架构,特别是路由存储的部分。 用户提到了RouteDefinitionRepository,这是负责存储路由定义的接口。我需要先理解这个接口的作用和它在整个路由机制中的位置。根据之前的了解,RouteDefinitionRepository用于加载和保存路由配置,可能涉及不同的实现类,比如内存存储或从配置中心读取。 接下来,我需要确定RouteDefinitionRepository的继承关系和主要方法。记得它可能有几个实现,比如InMemoryRouteDefinitionRepository,这个类将路由信息存储在内存中。另外,可能还有基于配置文件的实现,或者集成外部配置中心如Nacos、Consul的实现。 然后,我需要详细说明每个方法的功能。例如,save方法用于保存路由定义,delete方法用于删除,getRouteDefinitions返回所有路由的Flux流。这里需要解释反应式编程中的Flux,以及如何与Spring WebFlux结合使用。 还要考虑RouteDefinitionRepository如何与其他组件交互,比如RouteLocator,它可能使用Repository中的路由定义来创建可用的路由。需要说明整个流程,从加载路由配置到转换为Route对象的过程。 另外,用户可能对如何自定义RouteDefinitionRepository感兴趣,比如如何实现自己的存储逻辑,连接到数据库或远程配置服务。这部分需要给出一个简单的例子,说明如何通过实现接口来扩展功能。 需要注意源码中的关键点,比如事件发布机制。当路由变更时,是否会有RefreshRoutesEvent事件被触发,导致路由重新加载。这一点对于动态更新路由很重要,应该提及。 最后,总结RouteDefinitionRepository的作用,强调它在路由管理中的核心地位,以及不同实现方式的适用场景。确保解释清晰,结构合理,符合用户的需求。</think>Spring Cloud Gateway 中的 **`RouteDefinitionRepository`** 是路由定义(`RouteDefinition`)的核心存储器,负责路由配置的加载、存储与动态管理。以下从源码角度解析其设计逻辑与关键实现: --- ### 1. 接口定义 `RouteDefinitionRepository` 继承自 `ReactiveCrudRepository`,是一个反应式存储接口: ```java public interface RouteDefinitionRepository extends ReactiveCrudRepository<RouteDefinition, String> { Flux<RouteDefinition> getRouteDefinitions(); } ``` - **核心方法**: - `save()` / `delete()`:保存或删除路由定义(支持动态更新) - `getRouteDefinitions()`:返回所有路由的 `Flux` 流(反应式特性) --- ### 2. 默认实现:内存存储 **`InMemoryRouteDefinitionRepository`** 是默认实现,使用 `ConcurrentHashMap` 存储路由: ```java public class InMemoryRouteDefinitionRepository implements RouteDefinitionRepository { private final Map<String, RouteDefinition> routes = synchronizedMap(new ConcurrentHashMap<>()); @Override public Flux<RouteDefinition> getRouteDefinitions() { return Flux.fromIterable(routes.values()); } @Override public Mono<Void> save(Mono<RouteDefinition> route) { return route.doOnNext(r -> routes.put(r.getId(), r)).then(); } @Override public Mono<Void> delete(Mono<String> routeId) { return routeId.doOnNext(id -> routes.remove(id)).then(); } } ``` - **特点**: - 路由存储在 JVM 内存中,重启后失效 - 适用于静态配置或开发环境 --- ### 3. 动态路由扩展 通过自定义 `RouteDefinitionRepository` 可实现动态路由: #### 示例:从数据库加载路由 ```java @Bean public RouteDefinitionRepository jdbcRouteRepository(DataSource dataSource) { return new RouteDefinitionRepository() { @Override public Flux<RouteDefinition> getRouteDefinitions() { // 从数据库查询并转换为 RouteDefinition return Flux.fromIterable(queryRoutesFromDB()); } @Override public Mono<Void> save(Mono<RouteDefinition> route) { // 保存到数据库 return route.doOnNext(r -> saveToDB(r)).then(); } @Override public Mono<Void> delete(Mono<String> routeId) { // 从数据库删除 return routeId.doOnNext(id -> deleteFromDB(id)).then(); } }; } ``` --- ### 4. 与路由定位器的协作 `RouteDefinitionRouteLocator` 负责将 `RouteDefinition` 转换为可执行的 `Route`: ```java public class RouteDefinitionRouteLocator implements RouteLocator { private final RouteDefinitionRepository routeDefinitionRepository; public Flux<Route> getRoutes() { return routeDefinitionRepository.getRouteDefinitions() .map(this::convertToRoute); } private Route convertToRoute(RouteDefinition routeDefinition) { // 转换为 Route 对象(包含 Predicate 和 Filter) } } ``` - **流程**:`RouteDefinitionRepository` → `RouteDefinition` → `Route` --- ### 5. 动态刷新机制 当路由变更时,通过发布 `RefreshRoutesEvent` 事件触发更新: ```java // 示例:手动触发刷新 applicationContext.publishEvent(new RefreshRoutesEvent(this)); ``` --- ### 总结 - **核心角色**:`RouteDefinitionRepository` 是路由配置的抽象存储层 - **扩展性**:可通过自定义实现对接 Nacos/Consul/DB 等外部配置源 - **动态能力**:结合事件机制,实现路由热更新 - **性能考量**:反应式设计避免阻塞,适合高并发场景 实际应用中,建议结合 `Spring Cloud Config` 或 `Nacos` 实现持久化动态路由管理。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值