作者:5257wals_220 | 来源:互联网 | 2023-10-11 21:20
SpringCloudGateway扩展动态路由路由配置配置文件spring:application:name:sc-gwcloud:nacos:discovery:serv
Spring Cloud Gateway 扩展动态路由
路由配置
配置文件
spring:application:name: sc-gwcloud:nacos:discovery:server-addr: 127.0.0.1:8848config:server-addr: 127.0.0.1:8848file-extension: ymlshared-dataids: application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}gateway:discovery:locator:enabled: truelower-case-service-id: trueroutes: - id: nacos-getway-provider uri: lb://nacos-provider predicates: - Path=/service-02/** filters: - StripPrefix=1- id: nacos-getway-consumeruri: lb://nacos-comsumerpredicates:- Path=/service-01/**filters:- StripPrefix=1- id: sc-authuri: lb://sc-authpredicates:- Path=/sc-auth/**filters:- StripPrefix=1
硬编码配置
@Bean
public RouteLocator routeLocator(RouteLocatorBuilder builder) {return builder.routes().route("nacos-getway-provider",r -> r.path("/service-02/**").filters(f -> f.stripPrefix(2)).uri("lb://nacos-provider")).build();
}
Spring Cloud Gateway 原生配置路由的方式有配置文件、硬编码。但是这两种方式存在明显的缺陷:修改路由之后必须重新启动服务路由才能生效,非常不灵活。
路由初始化过程
- 不管是哪种方式配置路由,每一条路由信息最终都被封装为 RouteDefination。
- RouteDefinationLocator 是路由信息的装载器它只有一个方法 getRouteDefinitions()。
- RouteDefinationLocator 有多个实现类分别对应不同的路由加载方式。
- CachingRouteDefinitionLocator 是 RouteDefinationLocator 的一个包装类,它负责将读到的路由信息缓存到 Map。
- CompositeRouteDefinitionLocator 是 RouteDefinationLocator 的一个包装类,它负责组合RouteDefinationLocator 的各个实现类。
- PropertiesRouteDefinitionLocator 从配置文件中加载路由信息。
- DiscoveryClientRouteDefinitionLocator 从注册中心加载路由信息。
- RouteDefinitionRepository 从存储器中加载路由信息。这里的存储器包括内存、数据库
- RouteDefinitionRepository 有一个实现类 InMemoryRouteDefinitionRepository 。
- InMemoryRouteDefinitionRepository 从内存中加载路由信息。
- 没有 RouteDefinitionRepository 实例的情况下默认加载 InMemoryRouteDefinitionRepository 。
- 通过实现 RouteDefinitionRepository 来实现动态路由。
- 路由加载
- PropertiesRouteDefinitionLocator --> CompositeRouteDefinitionLocator
- RouteDefinitionRepository --> CompositeRouteDefinitionLocator
- DiscoveryClientRouteDefinitionLocator
- CompositeRouteDefinitionLocator
扩展思路
通过实现 RouteDefinitionRepository 接口扩展 Spring Cloud Gateway 支持从 Redis 中读取路由信息。
加入二级缓存(Map)。在实现 RouteDefinitionRepository 接口的getRouteDefinations() 方法时首先从二级缓存中读取路由信息,二级缓存为空时从 Redis 中 读取路由信息,再将路由信息写入到二级缓存中。
在在实现 RouteDefinitionRepository 接口的 save() / delete() 方法时通过 Redis 的发布订阅功能清空二级缓存
服务启动时通过监听WebServerIntialedEvent事件进行路由初始化。初始化过程中将 Mysql 中存储的路由信息读取出来存储到 Redis 中。
路由修改时首先更新 Redis ,再将路由信息持久化到 Mysql 中。通过发布 RefreshRoutesEvent 事件通过 Spring Cloud Gateway 更新路由。通过 Redis 的发布订阅功能清空二级缓存。持久化失败时回滚路由,通过发布事件重新进行路由初始化操作。
具体实现
- 前端页面。
- Controller 提供路由查询、更新接口。
- Service 提供路由查询、更新具体实现。
- 通过继承 RouteDefination 类支持序列化。创建 RouteDefinationVo 类封装数据库中存储的路由信息。
- 实现 RouteDefinationsRepository 接口重写 save() / delete() / getDefinations() 方法。
- 通过继承 ApplicationEvent 实现一个 DynamicRouteInitEvent 事件类 ,通过@EventListener 注解监听 WebServerIntialedEvent 、DynamicRouteInitEvent 事件对路由进行初始化。
- 创建 Redis 监听器,监听 topic 在Redis缓存更新时向指定的 topic 发布消息清空二级缓存或者重新初始化路由。
- 扩展 Redis 支持存储 Hash 形式的 value。