- disconf是什么: disconf根据英文的字面意思可以理解成分布式的配置中心(distributed configuration),无论大大小小的系统与配置中心的联系还是比较紧密的,对于业务中会用到,但不会经常变化,却又不适合在代码中耦合的变量,适合抽离到配置中心,如db、cache、还有业务中用到的一些变量配置都离不开配置中心的支持,配置中心的实现又分为好多种,有直接简单快捷的基于zookeeper实现,毕竟zookeeper配置管理也是它具备的一个基础能力,有基于consul的,大公司还有自研的等等,实现方案也是比较多,但是目标比较一致,要求配置中心高可用、数据更新实时性、承载更多的client请求的要求,有了如上的业务场景,从众多的方案中选用满足自己场景的方案即可!
- 如何用:1、安装disconf-web、zookeeper集群,不一一赘述了,详细可以参考官方文档:2、增加pom引入:
com.baidu.disconf disconf-client 2.6.36 @DisconfFile-类级别的注解,告诉这个类使用这个配置文件,这个配置文件就是通过disconf-web上传的文件@DisconfFileItem-方法级别的注解,注解在某一个getXX方法上,告诉这个GET方法使用配置文件内容的哪一个key(配置文件的规范是key=value)@DisconfItem-方法级别的注解,注解在某一个getXX方法上,告诉这个GET方法使用哪个配置项(这个配置项是在disconf-web上新建的一个key-value的值),注意:这个配置与分布式配置文件没有任何关系!!!以上注解的使用示例如下:
@Service@Scope("singleton")@DisconfFile(filename = "redis.properties")public class JedisConfig { // 代表连接地址 private String host; // 代表连接port private int port; /** * 地址, 分布式文件配置 * * @return */ @DisconfFileItem(name = "redis.host", associateField = "host") public String getHost() { return host; } public void setHost(String host) { this.host = host; } /** * 端口, 分布式文件配置 * * @return */ @DisconfFileItem(name = "redis.port", associateField = "port") public int getPort() { return port; } public void setPort(int port) { this.port = port; }}
@Servicepublic class Coefficients { public static final String key = "discountRate"; @Value(value = "2.0d") private Double discount; /** * 折扣率,分布式配置 * * @return */ @DisconfItem(key = key) public Double getDiscount() { return discount; } public void setDiscount(Double discount) { this.discount = discount; }}
4.2、非注解方式4.2.1、代码中使用方式与原生spring使用配置的方式相同,变量名使用@Value注解4.2.2、增加两个配置(支持各种文件格式的注入,仅properties文件更新时会对bean的属性更新,其他类型文件需要利用更新回调的配置):classpath:/autoconfig.properties classpath:/autoconfig2.properties classpath:/myserver_slave.properties classpath:/testJson.json classpath:/testXml2.xml myserver.properties @Service@Scope("singleton")@DisconfFile(filename = "redis.properties")@DisconfUpdateService(classes = {JedisConfig.class})public class JedisConfig implements IDisconfUpdate { protected static final Logger LOGGER = LoggerFactory.getLogger(JedisConfig.class); // 代表连接地址 private String host; // 代表连接port private int port; /** * 地址, 分布式文件配置 * * @return */ @DisconfFileItem(name = "redis.host", associateField = "host") public String getHost() { return host; } public void setHost(String host) { this.host = host; } /** * 端口, 分布式文件配置 * * @return */ @DisconfFileItem(name = "redis.port", associateField = "port") public int getPort() { return port; } public void setPort(int port) { this.port = port; } @Override public void reload() throws Exception { //配置变化的时候,创新创建某个jedisclient JedisUtils.reCreateConfig(host, port); }}
- 架构和原理讲解:1、引用官方的一个架构设计图:2、原理讲解: 2.1、用户把文件上传至disconf-web,或者在上面新建分布式配置项 2.2、服务启动时,通过扫描,获取哪些类、哪些属性需要获取分布式的配置,根据注解知道分布式配置项和配置文件是哪些 2.3、服务启动后,会通过http方式请求disconf-web,下载注解过的class所需要的配置文件到本地 2.4、文件下载到local以后,把注解中需要用到的文件、字段属性提取出来与注解的bean和属性建立对应关系,保存对应关系在内存中 2.5、根据文件或配置项增加zookeeper的监听,数据节点发生变更,刷新2.4中的提到的内存仓库 2.6、结合AOP的原理,当用户调用getXX时候,从内存中获取对应的值,实现配置的动态装载 2.7、非注解的方式,与AOP无关,通过重写PlaceholderResolvingStringValueResolver,对配置数据做重新构造,交由原来的spring处理,也就是为什么我们使用@Value取数据
- 优缺点总结: 优点:轻量级部署,对系统的侵入也较小,可以做到配置数据的实时生效,友好的兼容了spring框架,满足基本的配置应用场景 缺点:采用拉取的方式获取数据,当ZK的watch监测到节点数据变化,会做数据拉取,在客户端较多的情况下,容易对disconf-web形成并发的压力。