一次性吃透基于 Spring Cloud 动态配置实现动态数据源
笔者在一些项目中并未使用 Sentinel 提供的任何一种实现动态数据源的方式,而是选择自己实现动态数据源,因为这些项目被部署在 Kubernetes 平台上,所以可以利用 Kubernetes 提供的 ConfigMap 资源存储限流、熔断降级等规则,又因为 Spring Cloud Kubernetes 提供了 SpringCloud 动态配置接口的实现,所以我们不需要关心如何读取 ConfigMap 资源。
本节以实现 FlowRule 动态配置为例,详细介绍如何基于 Spring Cloud 动态配置实现动态数据源,主要分为 5 个步骤。
第一步,定义一个用于装载动态限流规则配置的 FlowRuleProps 类,代码如下:
第二步,定义限流规则转换器 FlowRuleConverter,将限流规则配置转换为 FlowRule 集合,代码如下:
第三步,定义限流规则动态数据源 FlowRuleDataSource,继承 AbstractDataSource 抽象类,并实现 readSource 方法,代码如下:
readSource 方法只需要实现获取 FlowRuleProps 实例并返回即可。
第四步,增强 FlowRuleDataSource,使 FlowRuleDataSource 能够监听到配置改变,代码如下:
增强一:实现 Spring InitializingBean 接口的 afterPropertiesSet 方法,在数据源对象创建时,初始化加载一次规则配置。
增强二:实现 SpringApplicationListener 接口的 onApplicationEvent 方法,监听动态配置改变事件(RefreshScopeRefreshedEvent)。
在监听到 RefreshScopeRefreshedEvent 事件时,首先调用 loadConfig 方法加载所有限流规则配置,然后调用 getProperty 方法获取 SentinelProperty 实例,最后调用 SentinelProperty 实例的 updateValue 方法通知 FlowRuleManager 的监听器更新限流规则配置。
第五步,定义一个 ApplicationRunner,在 Spring 容器刷新完成后,将 FlowRuleDataSource 实例的 SentinelProperty 实例注册给 FlowRuleManager,代码如下:
提示:在调用 FlowRuleManager#register2Property 方法将 FlowRuleDataSource 实例的 SentinelProperty 实例注册给 FlowRuleManager 时,FlowRuleManager 会自动给该 SentinelProperty 实例注册一个 FlowPropertyListener 实例。
至此,一个基于 Spring Cloud 动态配置实现的限流规则动态数据源就已经完成,整个工作流程如下:
当动态配置改变时,SpringCloud 会发送 RefreshScopeRefreshedEvent 事件,FlowRuleDataSource 的 onApplicationEvent 方法会被调用。
FlowRuleDataSource 调用 loadConfig 方法获取最新的配置。
FlowRuleDataSource#loadConfig 方法调用 readSource 方法获取 FlowRuleProps 实例,此时的 FlowRuleProps 实例已经装载了最新的配置。
FlowRuleDataSource#loadConfig 方法调用 FlowRuleConverter 实例的 convert 方法将 FlowRuleProps 实例转换为 FlowRule 集合。
FlowRuleDataSource 调用自身的 SentinelProperty 实例的 updateValue 方法通知所有监听器,并携带新的规则配置。
FlowPropertyListener 的 configUpdate 方法被调用,FlowPropertyListener 在 configUpdate 方法中更新 FlowRuleManager 缓存的限流规则配置。
提示:Sentinel 实现动态数据源的整体框架的设计值得我们学习,如数据转换器、监听器。
评论