博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
配置中心阿波罗学习之二 项目实战
阅读量:4091 次
发布时间:2019-05-25

本文共 4513 字,大约阅读时间需要 15 分钟。

一、背景

通过上一篇日志,我们已经将一个单机版的apollo server端搭建起来了,并且可以通过官方提供的demo实现最基本的配置文件的读取。接下来我主要通过一个实际的spring项目来演示如何利用apollo的java客户端实现项目的配置文件动态更新。

apollo的Java客户端可以通过纯java API,spring注解,springboot注解等形式绑定到我们的项目中,我项目使用的spring4.x搭建的,因此我使用spring注解方式将apollo客户端添加到我的工程中来。

二、实战

1.先引入apollo-client的maven依赖

com.ctrip.framework.apollo
apollo-client
1.1.0

2.创建自定义namespace,其中application是默认的namespace(一个namespace可以理解成一个properties文件的名称,因为我只用到了properties类型的配置文件)

创建好对应的namespace之后,页面会提示需要发布对应的key-value配置项,如果为空的话会导致Apollo client所在的工程报空指针异常!

3. 工程如何引入在Apollo中的各配置项?

namespace配置文件定位

apollo利用appid、cluster_name、namespace来最终定位一个配置文件,
其中 appid和cluster_name都是作为系统参数在应用启动之前就设置好了,而namespace作为客户端程序初始化的一个参数设定!

appid通过在项目的META-INF下面的app.prperties文件中指定,例:app.id=yanghe66966,其中yanghe66966为apollo中创建的一个appid,如何创建官网上面写的很详细,我这里就不罗嗦了

cluster_name通过jvm运行参数指定:“-Dapollo.cluster=default”

  • Apollo首先会尝试从用户指定的cluster名称的集群加载配置
  • 如果没找到,会从默认的集群(default)加载

namespace的获取,在javaconfig中,使用@EnableApolloConfig()注解,加载指定的namespace

@Configuration()@EnableApolloConfig(value = {"application","TEST2.RegistryCenter","TEST2.MessageMiddleware","TEST2.DistributedCaching"}, order = 10)//appllopublic class BasicConfig {	{		/**		 * 集群和环境设置未起作用		 */		System.setProperty("apollo.meta", "http://192.168.219.130:8080");		System.setProperty("idc", "DEV");//环境	}		@Bean    public PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {		        return new PropertySourcesPlaceholderConfigurer();    }}

创建与四个namespace一一对应的四个本地POJO对象,目的是将指定的配置文件封装到指定对象,便于整个工程调用

如RegistryCenterProperties类的代码如下,@component注解表示当前类的生命周期由spring负责,@value()注解就是使用的spring自带的注解

/** * 注册中心配置项 * @Description:  * @author  yangcheng * @date:   2019年6月23日 */@Componentpublic class RegistryCenterProperties {	Logger logger = LoggerFactory.getLogger(RegistryCenterProperties.class);	private final String curNamespace = "TEST2.RegistryCenter";	/**	 * 是否开启集群模式	 */	@Value("${CLUSTER_OPEN}")//官方建议给出默认值,如@Value("${CLUSTER_OPEN:ON}")--默认值为ON	private String clusteropen;	/**	 * 当前注册中心name	 */	@Value("${REGISTER_CENTER_NAME}")	private String curRegisterCenterName;	/**	 * zookkeeper相关的配置	 */	@Value("${ZK_ADDR}")	private String zkAddr;	@Value("${ZK_SESSION_OUTTIME}")	private int zkSessionOutTime;	//初次重试时间	@Value("${ZK_BASE_SLEEP_TIME_MS}")	private int zkBaseSleepTimeMs;	//最大重试次数	@Value("${ZK_MAX_RETRIES}")	private int zkMaxRetries;	/**	 * 监听namespace为TEST2.RegistryCenter的变化	 * @param changeEvent	 */	@ApolloConfigChangeListener(curNamespace)	private void anotherOnChange(ConfigChangeEvent changeEvent) {		if(curNamespace.equals(changeEvent.getNamespace())){			Set
propertySet = changeEvent.changedKeys(); for (String property : propertySet) { String newval = changeEvent.getChange(property).getNewValue();// System.out.println("old = " + clusteropen +";new = "+newval); /** * 亲测 变化后 properties对象通过Value注解赋值的属性会自动变动到最新值,不过捕获事件到属性值 * 变化有100毫秒左右的延迟! * 可以在app.properties中增加“apollo.autoUpdateInjectedSpringProperties=false”配置 * 关闭Value注解关联的属性自动刷新 */ try { Thread.sleep(500); } catch (InterruptedException e) { logger.error(e.getMessage()); }finally { try { //do something } catch (InterruptedException e) { logger.error("注册中心相关配置参数设定失败"+e.getMessage()); } } } } } public String getClusteropen() { return clusteropen; } public String getCurRegisterCenterName() { return curRegisterCenterName; } public String getZkAddr() { return zkAddr; } public int getZkSessionOutTime() { return zkSessionOutTime; } public int getZkBaseSleepTimeMs() { return zkBaseSleepTimeMs; } public int getZkMaxRetries() { return zkMaxRetries; } @Override public String toString() { return "RegistryCenterProperties [clusteropen=" + clusteropen + ", curRegisterCenterName=" + curRegisterCenterName + ", zkAddr=" + zkAddr + ", zkSessionOutTime=" + zkSessionOutTime + ", zkBaseSleepTimeMs=" + zkBaseSleepTimeMs + ", zkMaxRetries=" + zkMaxRetries + "]"; } }

需要使用对应配置时,只需要将RegistryCenterProperties注入到对应类中而后通过RegistryCenterProperties的get方法,比便可获取到相应的配置了

三、总结

1.apollo的使用方式有好几种,我这里只演示了使用spring方式引入apollo client的例子,不过大家也开出来了,其使用还是比较简单的,而且如果你原来项目中本来就是使用@value()注解形式引入配置文件的话,那么对已有代码的改动是很小的!我已经将我一个项目配置切换到apollo了。

2.要想在实际项目中使用的话,必须要考虑配置文件的动态配置策略,尤其是形如:zookeeper、消息中间件、分布式缓存等,一旦他的配置信息有变动,如何在不重启应用的情况下,快速切换对应的client,这个问题是必须要解决的,这里给大家提供一个思路(因为我就是这样子做的):譬如消息中间件,项目启动的时候需要将通过javaAPI实例化的client保存起来,然后等到监控到其对应的配置信息发生变动时,直接关闭原client,关闭之后利用新的配置信息重新实例化一个newclient对象!

转载地址:http://spcii.baihongyu.com/

你可能感兴趣的文章
JavaScript基础1:JavaScript 错误 - Throw、Try 和 Catch
查看>>
SQL基础总结——20150730
查看>>
SQL join
查看>>
JavaScript实现页面无刷新让时间走动
查看>>
CSS实例:Tab选项卡效果
查看>>
前端设计之特效表单
查看>>
前端设计之CSS布局:上中下三栏自适应高度CSS布局
查看>>
Java的时间操作玩法实例若干
查看>>
JavaScript:时间日期格式验证大全
查看>>
pinyin4j:拼音与汉字的转换实例
查看>>
XML工具代码:SAX从String字符串XML内获取指定节点或属性的值
查看>>
时间日期:获取两个日期相差几天
查看>>
责任链模式 Chain of Responsibility
查看>>
高并发与大数据解决方案概述
查看>>
解决SimpleDateFormat线程安全问题NumberFormatException: multiple points
查看>>
MySQL数据库存储引擎简介
查看>>
处理Maven本地仓库.lastUpdated文件
查看>>
Kafka | 请求是怎么被处理的?
查看>>
Java并发编程1-线程池
查看>>
CentOS7,玩转samba服务,基于身份验证的共享
查看>>