由来
在Spring Cloud Gateway源码解析-10-自定义Predicate实现黑名单中我们自定义了Predicate来实现黑名单,但发现每次更改黑名单规则都要重启项目来实现,因此需要将路由信息存储在外部数据源中,定时刷新SCG内存中的路由信息。
思路
在Spring Cloud Gateway源码解析-03-RouteDefinitionLocator、RouteLocator解析中我们已经介绍过RouteDefinitionRepository
,该接口在SCG中只有一个实现InMemoryRouteDefinitionRepository
,并且该接口继承了RouteDefinitionWriter
,RouteDefinitionWriter
中定义了save、delete
方法,通过方法名称可以知道是用来保存/添加/删除路由信息。
- 因此我们可以实现
RouteDefinitionRepository
用来保存从Redis中获取到的RouteDefinitionRedisRouteDefinitionRepository
,由于RouteDefinitionRepository
继承了RouteDefinitionLocator
,因此会被CompositeRouteDefinitionLocator
组合进去,从而被CachingRouteLocator
拿到对应的Redis中的RouteDefinition装换成Route。 - 有了地方存储Redis中的定义的RouteDefinition,那是不是要有一个角色用来获取Redis中的数据,并组装成RouteDefinition保存到
RedisRouteDefinitionRepository
中,因此需要定义RedisRouteDefinitionRepositoryOperator
用来从Redis中获取到数据库后生成RouteDefinition。可能我们的路由信息以后会放到MySQL、MongoDB等,因此可以抽象出一个从Repository中获取数据转换为RouteDefinition的接口RouteDefinitionRepositoryOperator
。 - 基于上边这些,我们就实现了当SCG启动时从Redis中获取数据转换为RouteDefinition,并保存到
RedisRouteDefinitionRepository
中,但是想要实现当修改了Redis中的路由信息后同步SCG更新,还不够,需要有一个类似Nacos的心跳机制,定时通知SCG去重新获取一次Redis中的数据。因此可以模仿Nacos的心跳机制实现RedisRouteDefinitionWatch
发送心跳事件,触发CachingRouteLocator
重新获取RouteDefinition来重新生成Route。
实现
RouteDefinitionRepositoryOperator
1 | json复制代码/** |
RedisRouteDefinitionRepositoryOperator
1 | json复制代码/** |
RedisRouteDefinitionRepository
1 | json复制代码/** |
RedisRouteDefinitionWatch
1 | json复制代码/** |
这样就大功告成了,实现了基于Redis配置路由信息并且可动态刷新的功能。
使用
1、Redis中数据:
2、将RedisRouteDefinitionWatch、RedisRouteDefinitionRepository、RedisRouteDefinitionRepositoryOperator放到Spring容器中,比如@Bean注入
通过以上两步,即可完成。代码写的比较简陋。
大家可自行验证下,亲测有效。代码仓库地址
本文转载自: 掘金