动态配置的实现原理
sentinel-datasource-extension模块是我们主要研究的模块,这是Sentinel实现动态数据源的核心,定义了动态数据源的接口并提供了抽象类。
SentinelProperty
SentinelProperty是Sentinel提供的一个接口,可被注册到Sentinel提供的各种规则的Manager(FlowRuleManager)中。SentinelProperty可以给SentinelProperty添加监听器,在配置改变时,用户可以调用SentinelProperty#updateValue方法,由该方法负责调用监听器去更新规则,而不需要调用FlowRuleManager#loadRules方法。同时,用户可以注册额外的监听器,在配置改变时做一些其他的事情。
SentinelProperty并不是在sentinel-datasource-extension模块中定义的接口,而是在sentinel-core模块中定义的接口,其源码如下:
addListener:添加监听器。
removeListener:移除监听器。
updateValue:通知所有监听器配置已更新,newValue参数为新的配置。
SentinelProperty默认使用的实现类是DynamicSentinelProperty,其实现源码如下:
从上述源码中可以看出,DynamicSentinelProperty使用Set存储已注册的监听器;
updateValue方法负责通知所有监听器,调用监听器的configUpdate方法。
在前面分析FlowRuleManager时,我们只关注了其loadRulesAPI,除了可以使用loadRules API加载规则配置,FlowRuleManager还提供了registerProperty API,用于注册一个SentinelProperty实例,以实现动态加载或更新规则配置。
使用SentinelProperty实现加载或更新限流规则配置的步骤如下:
给FlowRuleManager注册一个SentinelProperty实例,替换FlowRuleManager默认创建的SentinelProperty实例(因为外部拿不到默认的SentinelProperty)。
这一步由FlowRuleManager完成,FlowRuleManager会给SentinelProperty实例注册FlowPropertyListener监听器,该监听器负责更新FlowRuleManager.flowRules缓存的限流规则配置。
在应用启动或者规则配置改变时,只需要调用SentinelProperty#updateValue方法,由updateValue通知FlowPropertyListener监听器去更新限流规则配置。
FlowRuleManager支持使用SentinelProperty加载或更新限流规则配置的实现源码如下:
LISTENER:PropertyListener接口的实现类实例,用于监听规则配置更新,在规则配置更新时更新flowRules字段缓存的限流规则配置。
currentProperty:当前使用的SentinelProperty实例,默认会创建一个DynamicSentinelProperty实例。
register2Property:用于注册SentinelProperty实例。
实现更新缓存的限流规则配置的FlowPropertyListener是FlowRuleManager的一个内部类,其源码如下:
PropertyListener接口定义了如下两个方法:
configUpdate:在更新规则配置时被调用,被调用的时机是SentinelProperty的updateValue方法被调用时。
configLoad:在首次加载规则配置时被调用,是否被调用由SentinelProperty的实现类决定。DynamicSentinelProperty没有调用这个方法。
所以,现在有如下两种方法可用于更新限流规则配置:
调用FlowRuleManager#loadRules方法。
给FlowRuleManager注册一个SentinelProperty实例,并调用SentinelProperty实例的updateValue方法。
ReadableDataSource
Sentinel将读和写数据源抽离成两个接口(早期版本只有读接口,写接口是之后的版本才添加的功能),目前来看,写接口只在热点参数限流模块中被使用。事实上,使用读接口就可以满足我们的需求。ReadableDataSource接口的定义如下:
ReadableDataSource是一个泛型接口,参数化类型S代表用于装载从数据源中读取的配置的类型,参数化类型T代表对应Sentinel中的规则类型。例如,我们可以定义一个FlowRuleProps类,用于装载从yml配置文件中读取的限流规则配置,然后将FlowRuleProps实例转换为FlowRule实例,所以S可以被替换为FlowRuleProps,T可以被替换为List。
ReadableDataSource接口定义的方法说明如下:
loadConfig:加载配置。
readSource:从数据源中读取配置,数据源既可以是yaml配置文件,也可以是MySQL、Redis等,由实现类决定从哪种数据源中读取配置。
getProperty:获取SentinelProperty实例。
close:用于关闭数据源,例如,在使用文件存储配置时,可以在此方法中实现关闭文件输入流功能。
如果动态数据源提供SentinelProperty,则可以调用getProperty方法获取动态数据源提供的SentinelProperty实例,并将此SentinelProperty实例注册给规则管理器,这样动态数据源在读取到配置时就可以调用自身SentinelProperty实例的updateValue方法通知规则管理器更新规则。
AbstractDataSource是一个抽象类,该类可实现ReadableDataSource接口,用于简化具体动态数据源的实现,其子类只需要继承AbstractDataSource抽象类并实现readSource方法即可。
AbstractDataSource抽象类的源码如下:
AbstractDataSource抽象类要求所有子类都必须提供一个数据转换器(Converter)。
Converter用于将S类型的实例转换为T类型的实例,如将用于装载yaml配置的FlowRuleProps实例转换为FlowRule集合。
AbstractDataSource实例会在构造方法中创建DynamicSentinelProperty实例,因此子类无须创建SentinelProperty实例。
AbstractDataSource实例实现loadConfig方法,首先调用子类实现的readSource方法从数据源中读取配置,返回的实例类型为S,然后调用Converter实例的convert方法,将S类型的实例转换为T类型的实例。
Converter接口的定义如下:
convert:将类型为S的参数source转换为类型为T的实例。
本文给大家讲解的内容是深度解析微服务高并发动态数据源 :动态配置的实现原理
下篇文章给大家讲解的内容是深度解析微服务高并发动态数据源 :基于Spring Cloud动态配置实现动态数据源
感谢大家的支持!
领取专属 10元无门槛券
私享最新 技术干货