从0到1手写配置中心config之实现配置中心客户端

  1. 配置加载原理

在Spring中PropertySource类实现了所有属性的实例化。

启动赋值:

  • 定义自定义属性配置源,从config-server获取全局属性;
  • Spring启动时,插入自定义属性配置源;
  • 绑定属性会优先使用,给自定义属性配置源赋值。

动态更新:

  • client端和server端保持心跳检测,当有配置变动时获取新配置;
  • 对于@Value的字段需要反射赋值;
  • 对于@ConfigurationProperties配置类可以发送刷新事件。

优先级:

  • 自定义配资源;
  • 来自系统属性;
  • 来自application.yaml;
  • 来自application.properties;
  • 来自spring内置属性。
  1. 自定义客户端注解

使用该注解就能加载客户端程序

图片

  1. 自定义ConfigService

接口: 获取所有配置名称;根据名称获取配置

图片

实现类:使用Map保存所有配置信息

图片

  1. 自定义配置源

继承了EnumerablePropertySource,从ConfigService中获取属性信息。

图片

  1. 自定义配置源处理器
  • 实现BeanFactoryPostProcessor接口重新bean的后置处理逻辑;
  • 实现 EnvironmentAware接口获取环境变量;
  • 实现 PriorityOrdered接口定义优先级。

图片

在postProcessBeanFactory()方法中

  • 通过http请求到 config-server 获取配置;
  • 创建自定义配置源;
  • 创建组合配置源,可以加载多个自定义的配置源;
  • 放到属性源环境变量的最前面。

程序启动时,debug可以看到,配置中心的值加载到env的最前面了。

图片

  1. 手动注册bean

配置中心的客户端只是一个jar包,不是web项目,不能自动扫描注解包,需要手动注册bean。

通过实现ImportBeanDefinitionRegistrarle完成手动注册。一开始先判断是否存在,避免重复加载,然后再注册。

图片

  1. 测试

新建一个web工程,在启动类中使用注解@EnableMidnightConfig启动配置中心客户端。

在demo工程中,使用了@Value的方式和@ConfigurationProperties配置的方式。

图片

图片

工程中默认的配置值midnight.a=a100。

图片

配置中心默认的是midnight.a=dev500。

图片

启动工程,查看日志,两种配置方式都是dev500,说明配置中心起作用了。

图片

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

从0到1手写配置中心config之基于h2的config Server

  1. 添加依赖

新建的web工程中添加h2的依赖

图片

  1. 添加h2的配置
  • 设置数据源和密码
  • 设置初始化sql语句
  • 打开h2的控制台

图片

初始化语句创建一个config表,保存服务配置信息。

图片

  1. 完成CRUD接口

controller类

图片

mapper接口

图片

  1. 测试

在web控制台可以看到sql已经初始化完成,crud接口也比较简单。

图片

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

从0到1手写注册中心registry之主从数据同步

集群选主完成后,从节点需要从主节点同步数据。

一、快照数据

同步的快照数据是描述注册中心的服务信息。

  • registry: 每个服务对应的实例;
  • versions:每个服务的版本信息;
  • timestamps:每个服务的时间戳;
  • version:当前服务版本信息;

图片

二、主从数据同步

在定时任务中,依次执行:服务状态更新,集群选主,主从数据同步。

图片

当前节点不是主节点,并且版本信息小于主节点的版本,就认为是从节点,就需要从主节点同步数据,以保证整个集群对外数据的一致性。

发起http请求,获取快照数据,然后根据快照数据恢复到当前从节点注册中心数据。

图片

恢复数据的逻辑就是清空,再添加。

图片

三、测试

依次启动8084、8085、8086,主节点是8084,从节点是8085和8086。

向主节点8084注册服务

图片

从节点8086也能查询到服务,说明主从数据同步成功。

图片