博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Netflix Archaius 分布式配置管理依赖构件
阅读量:6653 次
发布时间:2019-06-25

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

hot3.png

概述

archaius是Netflix公司开源项目之一,基于java的配置管理类库,主要用于多配置存储的动态获取。主要功能是对apache common configuration类库的扩展。在云平台开发中可以将其用作分布式配置管理依赖构件。同时,它有如下一些特性:

  • 动态类型化属性

  • 高效和线程安全的配置操作

  • 配置改变时的回调机制

  • 轮询框架

  • JMX,通过Jconsole检查和调用操作属性

  • 组合配置

技术分享

image.png

适用场景

对于传统的单体应用,properties等配置文件可以解决配置问题,同时也可以通过maven profile配置来区别各个环境,但在一个几百上千节点的的微服务生态中,微服务采用多种语言开发,配置文件格式多样,如何把每个微服务的配置文件都进行更新,并且很多时候还需要重启服务,是一件无法忍受的事情。所以,对于微服务架构而言,一个通用的配置中心是必不可少的。

新接口逻辑上线,老接口面临迁移,开发测试完成后,马上要上线。但是接口调用发的研发同学对新接口的稳定性、性能存在一定的质疑,为了避免风险,要求可以上线后紧急切换回老接口。这时候我们就需要一个手动开关。所以对于类似需求,一个通用的配置中心是必不可少的。

Archaius提供的DynamicIntProperty类可以在配置发生变化时动态地获取配置,并且不需要重启应用,而底层的配置存储,建议使用zookeeper进行存储,Archaius作为客户端的类库使用。

代码案例

引入依赖

    
com.netflix.archaius
    
archaius-core

自定义Configuration

PropertiesConfiguration

public class PropertiesConfiguration extends DynamicConfiguration {    private static final Logger LOGGER = LoggerFactory.getLogger(PropertiesConfiguration.class);    private static final int INITIAL_DELAY_MILLIS = 0;    private static final int DELAY_MILLIS = 60 * 1000;    private static final boolean IGNORE_DELETES_FROM_SOURCE = true;    public PropertiesConfiguration(String confDir) {        this(new String[]{confDir});    }    public PropertiesConfiguration(final String...confDirs) {        String[] propertiesPaths = Lists.newArrayList(Iterables.concat(Iterables.transform(Arrays.asList(confDirs), new Function
>() {            @Nullable            @Override            public List
 apply(String confDir) {                Assert.isTrue(new File(confDir).isDirectory(), StringUtil.format("路径[{}]无法查找[.properties]文件", confDirs));                String[] propertiesPaths = getPaths(confDir);                if (ArrayUtils.isNotEmpty(propertiesPaths)) {                    return Lists.newArrayList(propertiesPaths);                } else {                                        return Lists.newArrayList();                }            }        }))).toArray(new String[0]);        if (ArrayUtils.isNotEmpty(propertiesPaths)) {            super.startPolling(new URLConfigurationSource(propertiesPaths), new FixedDelayPollingScheduler(INITIAL_DELAY_MILLIS, DELAY_MILLIS, IGNORE_DELETES_FROM_SOURCE));        }        ConfigurationLog.successInit(PropertiesConfiguration.class, this.getProperties());    }    private static String[] getPaths(String confDir) {        try {            URL configHome = new File(confDir).toURI().toURL();            List
 urls = new ArrayList
();            for (String filename : FileUtil.scan(confDir, ".properties$")) {                String url = configHome.toString() + filename;                urls.add(url);            }            return urls.toArray(new String[urls.size()]);        } catch (MalformedURLException e) {            throw Throwables.propagate(e);        }    }}

SystemConfiguration

public class SystemConfiguration extends ConcurrentMapConfiguration {    private static final Logger LOGGER = LoggerFactory.getLogger(SystemConfiguration.class);    public SystemConfiguration() {        super();        this.loadProperties(System.getProperties());        ConfigurationLog.successInit(SystemConfiguration.class, this.getProperties());    }}

同理,可以使用zookeeper client 封装一个基于zookeeper的 ConcurrentMapConfiguration

初始化

private static final ConcurrentCompositeConfiguration compositeConfig = new ConcurrentCompositeConfiguration();public synchronized static void init() {    Preconditions.checkState(! hadInit, StringUtil.format("[{}]只能加载一次!", ConfigAdapter.class.getSimpleName()));    Preconditions.checkState(compositeConfig.getConfigurations().size() > 1,            StringUtil.format("[{}]没有加载任何配置", ConfigAdapter.class.getSimpleName()));    if (! ConfigurationManager.isConfigurationInstalled()) {        ConfigurationManager.install(compositeConfig);        Preconditions.checkState(ConfigurationManager.isConfigurationInstalled(), StringUtil.format("[{}]加载失败!",                ConfigAdapter.class.getSimpleName()));    }    Iterable
 configurationNames = Iterables.transform(compositeConfig.getConfigurations(), new Function
() {        @Nullable        @Override        public String apply(AbstractConfiguration input) {            return input.getClass().getSimpleName();        }    });    ConfigurationLog.successInit(ConfigAdapter.class, getAll());    hadInit = true;}

获取值

 public static DynamicBooleanProperty getDynamicBool(String key, boolean defaultValue) {        return getFactory().getBooleanProperty(key, defaultValue);    }private static DynamicPropertyFactory getFactory() {        return DynamicPropertyFactory.getInstance();    }

注意

  • 在设置的时刻获取配置,配置源不会随着System#properties里面的配置更新而更新

  • 更新配置方法不会更新实际的property文件,仅仅为更新内存数据,重启后失效

  • 微服务都从配置中心动态的读取配置信息,而配置中心又在从配置源同步配置,所以这里就很自然的出现了一个读写安全的问题,好消息是Archaius已经解决了这个问题,Archaius是线程安全的,读写可以并发进行。

https://github.com/Netflix/Hystrix/wiki/Configuration#CommandProperties

转载于:https://my.oschina.net/xiaominmin/blog/1590730

你可能感兴趣的文章
mysql关于字符串字段数据类型
查看>>
使用merge同时执行insert和update操作
查看>>
Ubantu16.4的安装过程以及基本配置
查看>>
imx6平台qt锯齿原因分析
查看>>
HashMap与ConcurrentHashMap的区别
查看>>
LXD 2.0 系列(四):资源控制
查看>>
yum安装nginx详解
查看>>
"ImportError: cannot import name OVSLegacyKernelSwitch"
查看>>
2017第3周五
查看>>
[Unity3D]Unity+Android交互教程——让手机"动"起来
查看>>
jQuery EasyUI 入门简介
查看>>
centos下完全卸载mysql
查看>>
android手机获取手机号
查看>>
Android ListView带CheckBox实现单选
查看>>
PostgreSQL Table Partitioning<转>
查看>>
oracle sql语言模糊查询--通配符like的使用教程
查看>>
Web 进化
查看>>
csv文件已经python内置csv模块
查看>>
BZOJ 3781: 小B的询问 [莫队]
查看>>
git call failed: [git clone Could not resolve host: git.openstack.org
查看>>