14 May 2024 |
- DistributedLocks实现
- 自动注入数据源。创建连接,保证不影响其他连接。
- locked原子变量判断是否加锁成功;
- Executor 定时任务,尝试获取锁。

- init()初始化方法
使用注解@PostConstruct初始化,使用数据源创建连接。
开启定时任务,每隔5秒执行一次。

- tryLock()方法
尝试获取锁,获取成功,locked=true,否则为false。

- lock() 加锁
- 关闭自动提交事务;
- 设置事务隔离级别为RC;
- 设置锁超时时间innodb_lock_wait_timeout为5秒;
- 执行锁定语句for update加锁
- 事务不要commit或rollback,否则锁就释放了
- 根据locked状态判断是第一次获取到锁,还是后续的锁重入。

- closed()方法
使用@PreDestroy注解销毁bean时,连接回滚,并关闭。

- 测试
- 分别用端口9129和9130启动config-server
假如9129先启动,观察日志成功获取到锁了,并在定时任务重不断重入。

- 9130端口后启动,不会获取到锁,等待5秒后,抛出超时异常。


锁状态locked表示已经持有

源码:https://github.com/midnight2104/midnight-config/tree/v5
10 May 2024 |
- 定义SpringValueProcessor处理类
- 实现BeanPostProcessor后置处理器接口,扫描所有的Spring value,保存起来。
- 实现ApplicationListener接口,在配置变更时,更新所有的spring value

- 实现BeanPostProcessor后置处理器接口
实现postProcessBeforeInitialization()方法。通过工具类找到所有带有@Value的bean,遍历每个字段。通过helper工具类抽取注解上面的表达式,构建SpringValue对象并保存起来。

使用SpringValue对象封装@Value注解信息。

一个SpringValue对象如下:

- 实现onApplicationEvent方法
- 事件变更时,自动实现该方法;
- 从前面保存的holder中获取SpringValues;
- 遍历集合,解析获取属性值;
- 通过反射重新赋值。

- 测试
- 启动 config-server
- 启动config-client
初始值如下:都是dev100

更新配置中心的值

观察config-demo的日志

再次获取值,就已经动态发生了变化。

源码:https://github.com/midnight2104/midnight-config/tree/v4
09 May 2024 |
- 在PropertySourcesProcessor中,需要通过http从config-server获取配置。

- 使用ConfigMeta包装服务信息

- 在MidnightConfigService接口中添加默认实现类
- 继承MidnightRepositoryChangeListener接口;
- 获取默认的MidnightRepository;
- 创建MidnightConfigServiceImpl实现类;
- 添加listener

- 定义MidnightRepositoryChangeListener,用于事件监听的回调接口
- onChange() 执行方法
- ChangeEvent变动事件,传递参数

- 定义MidnightRepository接口
- 提供默认实现类
- getConfig()获取配置
- addListener()添加监听器

- MidnightRepositoryImpl实现从server获取配置
- meta保存服务配置源信息;
- versionMap保存server版本号,用于比较本地和远程版本信息,用于比对配置是否发生变化;
- configMap保存一个ns服务下所有配置信息;
- executor定时任务,监听服务端配置是否发生变化;
- listeners保存监听器。

- findAll()接口
发起http请求,从config-server获取所有配置信息。

- heartbeat() 心跳检测
- 发起http请求,从配置中心服务端获取最新版本信息;
- 当远程版本信息大于本地版本信息时,说明配置发生了变化。
- 保存最新版本信息;
- 从配置中心重新获取所有配置信息;
- 保存最新的配置信息;
- 发布配置发生变更事件

- onChange() 发布事件
- 更新本地最新配置
- 通过Spring发布环境变更事件。事件类EnvironmentChangeEvent来自于SpringCloud,解决微服务架构下配置热更新问题。

- 重新绑定配置
当EnvironmentChangeEvent事件发布之后,会重新绑定PropertySource,调用getProperty()方法获取最新配置。

- @ConfigurationProperties 中的属性就会被更新

- 测试
- 启动config-server
- 启动config-client
- 观察日志,最开始的值如下

发现版本发生了变化,重新获取了配置,并发布了EnvironmentChangeEvent事件。


源代码:
https://github.com/midnight2104/midnight-config/tree/v3