Netflix的archaius

intro

archaius是Netflix oss(open source software)的配置核心。它有很强大的功能,可以读配置文件的配置,系统的配置,还有zookeeper的配置等等的。

archaius原意是一种变色龙,那么含义就是根据环境的不同可以改变配置。

我们会讲一下它的基本用法和各个配置的覆盖。

pom

各种依赖冲突把我折腾的都快放弃了,最后调出来的可用版本为:

<dependencies>
		<dependency>
			<groupId>org.apache.curator</groupId>
			<artifactId>curator-framework</artifactId>
			<version>2.8.0</version>
		</dependency>
		<dependency>
			<groupId>org.apache.curator</groupId>
			<artifactId>curator-recipes</artifactId>
			<version>2.8.0</version>
		</dependency>

		<dependency>
			<groupId>com.netflix.archaius</groupId>
			<artifactId>archaius-core</artifactId>
			<version>0.7.4</version>
		</dependency>

		<dependency>
			<groupId>com.netflix.archaius</groupId>
			<artifactId>archaius-zookeeper</artifactId>
			<version>0.7.4</version>
		</dependency>

		<dependency>
			<groupId>com.netflix.curator</groupId>
			<artifactId>curator-test</artifactId>
			<version>1.3.3</version>
		</dependency>

		<dependency>
			<groupId>commons-configuration</groupId>
			<artifactId>commons-configuration</artifactId>
			<version>1.10</version>
		</dependency>


		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.12</version>
			<scope>compile</scope>
		</dependency>

	</dependencies>

basics

一个掌管配置的框架,一定能读resources下的配置文件。

先建一个config.properties,archaius找resources下的配置文件时,默认找的名字就是config.properties

stringprop=propvalue
listprop=value1, value2, value3
mapprop=key1=value1, key2=value2
longprop=100

我们存放普通的string值,list,map,还有long值,看它是不是都能读。

@Test
	public void testBasicStringProps() throws InterruptedException {
		DynamicStringProperty sampleProp = DynamicPropertyFactory.getInstance().getStringProperty("stringprop", "");
		System.out.println(sampleProp.get());
	}

取出stringprop对应的value,如果没有的话就是空字符串。

DynamicPropertyFactory.getInstance()是一个double check的单例模式:

public static DynamicPropertyFactory getInstance() {
        if (config == null) {
            synchronized (ConfigurationManager.class) {
                if (config == null) {
                    AbstractConfiguration configFromManager = ConfigurationManager.getConfigInstance();
                    if (configFromManager != null) {
                        initWithConfigurationSource(configFromManager);
                        initializedWithDefaultConfig = !ConfigurationManager.isConfigurationInstalled();
                        logger.info("DynamicPropertyFactory is initialized with configuration sources: " + configFromManager);
                    }
                }
            }
        }
        return instance;
    }
	@Test
	public void testBasicListProps() {
		DynamicStringListProperty listProperty = new DynamicStringListProperty("listprop", Collections.<String>emptyList());
		listProperty.get().stream().forEach(System.out::println);
	}

取出list的值。

@Test
	public void testBasicMapProps() {
		DynamicStringMapProperty mapProperty = new DynamicStringMapProperty("mapprop", Collections.emptyMap());
		Map<String, String> map = mapProperty.getMap();
		map.forEach((k, v) -> System.out.println(k + "\t" + v));
	}

取出map的值。

@Test
	public void testBasicLongProperty() {
		DynamicLongProperty longProp = DynamicPropertyFactory.getInstance().getLongProperty("longprop", 1000);
		System.out.println(longProp.get());
	}

取出long值。默认是1000,但是我们在配置文件中配了,所以结果是100。


config.properties override

如果我的配置文件不叫config.properties,比如叫newconfig.properties呢?

我们在newconfig.properties中写:

newstringprop=newstringvalue

如何把它加入进来呢?

@Before
	public void setup() throws IOException {
		ConfigurationManager.loadCascadedPropertiesFromResources("newconfig");
		//System.setProperty("archaius.configurationSource.defaultFileName", "newconfig.properties");
	}
@Test
	public void testBasicStringProps() throws InterruptedException {
		DynamicStringProperty sampleProp = DynamicPropertyFactory.getInstance().getStringProperty("newstringprop", "");
		System.out.println(sampleProp.get());
	}

这样子就可以取出newstringprop

另一方面,config.properties中的值照旧有效。

如果你使用System.setProperty()的方式:

@Before
	public void setup() throws IOException {
		//ConfigurationManager.loadCascadedPropertiesFromResources("newconfig");
		System.setProperty("archaius.configurationSource.defaultFileName", "newconfig.properties");
	}


那就把newconfig.properties当作默认配置文件了。这时config.properties就失效了。


我们也可以进行配置文件的关联动态地改值。比如对于环境的修改:

sample.properties中:

sampleprop=samplevalue
@next=sample-$(@environment).properties 

现在我这个sampleprop的值要去sample-xxx.properties的文件中找,@environment需要我们动态地给值。

比如最终找的是sample-test.properties

sampleprop=propvalue-test

测试:

public class TestArchaiusOverriding {
	@Before
	public void setUp() throws IOException {
		ConfigurationManager.getConfigInstance().setProperty("@environment", "test");
		ConfigurationManager.loadCascadedPropertiesFromResources("sample");
	}

	@Test
	public void testOverringEnvironment() {
		DynamicStringProperty sampleProperty = DynamicPropertyFactory.getInstance().getStringProperty("sampleprop", "");
		System.out.println(sampleProperty.get());
	}
}

more configurations and overriding

配置当然还有很多。在接下来的测试中,我们会使用zookeeper配置,自定义的map配置,和系统配置。

启动zookeeper,建立/config节点。

//zookeeper的根路径,在自己的zookeeper中建好这个节点
	private static final String CONFIG_ROOT_PATH = "/config";
	//客户端
	private static CuratorFramework client;
	//zookeeper的配置资源类
	private static ZooKeeperConfigurationSource zkConfigSource;
	//自定义的配置类,就是一个map
	private static ConcurrentMapConfiguration mapConfig;

	private static final Charset charset = Charset.forName("UTF-8");

	@BeforeClass
	public static void setUp() throws Exception {
		//连上本地的zookeeper
		client = CuratorFrameworkFactory.newClient("localhost:2181", new ExponentialBackoffRetry(1000, 3));
		client.start();

		//本地缓存
		zkConfigSource = new ZooKeeperConfigurationSource(client, CONFIG_ROOT_PATH);
		zkConfigSource.start();

		// 设置系统值
		System.setProperty("test.key4", "test.value4-system");
		System.setProperty("test.key5", "test.value5-system");

		final ConcurrentMapConfiguration systemConfig = new ConcurrentMapConfiguration();
		//加载系统值到一个map
		systemConfig.loadProperties(System.getProperties());

		//动态监视zookeeper配置的变化
		final DynamicWatchedConfiguration zkDynamicOverrideConfig = new DynamicWatchedConfiguration(zkConfigSource);

		//自定义map配置
		mapConfig = new ConcurrentMapConfiguration();
		mapConfig.addProperty("test.key1", "test.value1-map");
		mapConfig.addProperty("test.key2", "test.value2-map");
		mapConfig.addProperty("test.key3", "test.value3-map");
		mapConfig.addProperty("test.key4", "test.value4-map");

		//把三种配置合起来
		final ConcurrentCompositeConfiguration compositeConfig = new ConcurrentCompositeConfiguration();
		compositeConfig.addConfiguration(zkDynamicOverrideConfig, "zk dynamic override configuration");
		compositeConfig.addConfiguration(mapConfig, "map configuration");
		compositeConfig.addConfiguration(systemConfig, "system configuration");

		// 设置zookeeper的配置
		setZkProperty("test.key1", "test.value1-zk");
		setZkProperty("test.key2", "test.value2-zk");
		setZkProperty("test.key4", "test.value4-zk");

		//加载配置
		ConfigurationManager.install(compositeConfig);
	}







这三种配置,有一些key是重合的。

比如mapConfigtest.key1test.key2test.key4就与zookeeper一样,但是值是不同的。

然后我们这里使用的是zookeeper的客户端框架curator。

private static void setZkProperty(String key, String value) throws Exception {

		final String path = CONFIG_ROOT_PATH + "/" + key;

		byte[] data = value.getBytes(charset);

		//查看key是否原来存在,有就更新,没有就建
		try {
			// attempt to create (intentionally doing this instead of checkExists())
			client.create().creatingParentsIfNeeded().forPath(path, data);
		} catch (KeeperException.NodeExistsException exc) {
			// key already exists - update the data instead
			client.setData().forPath(path, data);
		}

	}

这个方法通过zookeeper的client来创建或者更新配置中的值。

//关闭配置资源
	@AfterClass
	public static void tearDown() throws Exception {
		zkConfigSource.close();
	}

最后还要关一下ZooKeeperConfigurationSource

开始测试:

@Test
	public void testZkPropertyOverride() throws Exception {
		setZkProperty("test.key1", "test.value1-zk");
		// there is an override from ZK, so make sure the overridden value is being returned
		System.out.println(DynamicPropertyFactory.getInstance().getStringProperty("test.key1", "default").get());
	}



zookeeper覆盖mapConfig。

@Test
	public void testNoZkPropertyOverride() throws Exception {
		// there's no override, so the map config value should be returned
		System.out.println(DynamicPropertyFactory.getInstance().getStringProperty("test.key3", "default")
				.get());
	}


没被zookeeper覆盖,返回mapConfig中的值。

@Test
	public void testDefault() throws Exception {
		// there's no property set, so the default should be returned
		System.out.println(DynamicPropertyFactory.getInstance().getStringProperty("test.key99", "default")
				.get());
	}


没有test.key99这个key,返回default。

@Test
	public void testSystemPropertyOverride() throws Exception {
		// there's a system property set, but this should not trump the zk override
		System.out.println(DynamicPropertyFactory.getInstance().getStringProperty("test.key4", "default")
				.get());

		// there's a system property set, but no other overrides, so should return the system property
		System.out.println(DynamicPropertyFactory.getInstance().getStringProperty("test.key5", "default")
				.get());
	}





systemConfigmapConfig和zookeeper中都有test.key4,最终胜出的是zookeeper。

test.key5是系统属性独有的。

	@Test
	public void testUpdatePropertyOverride() throws Exception {
		setZkProperty("test.key1", "test.value1-zk");

		// update the map config's property and assert that the value is still the overridden value
		mapConfig.setProperty("test.key1", "prop1");
		System.out.println(DynamicPropertyFactory.getInstance()
				.getStringProperty("test.key1", "default").get());
	}




mapConfig试图修改test.key1的值,不过那是不会成功的。

	@Test
	public void testUpdateZkProperty() throws Exception {
		setZkProperty("test.key1", "test.value1-zk-override");

		System.out.println(DynamicPropertyFactory.getInstance()
				.getStringProperty("test.key1", "default").get());
	}





zookeeper一动手,就能改成功。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值