Netflix Archaius 分布式配置管理依赖构件

Archaius 配置管理API,包含一系列配置管理API,提供动态类型化属性、线程安全配置操作、轮询框架、回调机制等功能。

概述

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

  • 动态类型化属性
  • 高效和线程安全的配置操作
  • 配置改变时的回调机制
  • 轮询框架
  • JMX,通过Jconsole检查和调用操作属性
  • 组合配置

image.png

适用场景

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

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

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

代码案例

引入依赖

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

自定义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<String, List<String>>() {
            @Nullable
            @Override
            public List<String> 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<String> urls = new ArrayList<String>();
            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<String> configurationNames = Iterables.transform(compositeConfig.getConfigurations(), new Function<AbstractConfiguration, String>() {
        @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是线程安全的,读写可以并发进行。

个人介绍: 高广超:多年一线互联网研发与架构设计经验,擅长设计与落地高可用、高性能互联网架构。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Linyb极客之路

并发编程之Semaphore

一、简介 Semaphore(信号量)是用来控制同时访问特定资源的线程数量,它通过协调各个线程,以保证合理的使用公共资源。很多年以来,我都觉得从字面上很难理解...

4168
来自专栏老码农专栏

原 荐 一场版本升级引发的性能血案 - 之数

2203
来自专栏Java编程技术

Netty学习笔记(一)

Netty是一种可以轻松快速的开发类似协议服务器和客户端网络应用程序的NIO客户端服务器框架,它大大简化了TCP或者UDP服务器的网络编程,但是你仍然可以访问和...

1442
来自专栏一个番茄说

Swift中防止ptrace依附

在移动开发中,安全是一个很重要的话题,当然安全是没有绝对的,只能说尽可能的提高安全性。在iOS的开发中,为了防止别人窥视我们的App,我们得采用一些手段来进行防...

1083
来自专栏java达人

java 处理xml的三种技术

最初,XML 语言仅仅是意图用来作为 HTML 语言的替代品而出现的,但是随着该语言的不断发展和完善,人们越来越发现它所具有的优点:例如标记语言可扩...

2185
来自专栏恰同学骚年

操作系统核心原理-4.线程原理(下):死锁基础原理

我们都见过交通阻塞,一大堆汽车因为争夺行路权,互不相让而造成阻塞,又或者因为车辆发生故障抛锚或两辆车相撞而造成道路阻塞。在这种情况下,所有的车都停下来,谁也无...

1032
来自专栏老码农专栏

TodoBackend展示应用以及ActFramework的实现

1225
来自专栏微信公众号:Java团长

即将发布的 JDK 10 有 109 项新特性,你喜欢哪些?

按计划,JDK 10 将于 3 月 20 日正式发布。据前 Oracle 员工 Simon Ritter 的统计,JDK 10 总共包含 109 项新特性。当然...

622
来自专栏工科狗和生物喵

FreeRTOS-Qemu 实现三任务同步通信机制以及API信息

---- 1. 本次作业的考察要点: 作业地址:https://github.com/HustWolfzzb/STM32F429DiscoveryFreeRTO...

1K6
来自专栏吉浦迅科技

DAY71:阅读Device-side Launch from PTX

我们正带领大家开始阅读英文的《CUDA C Programming Guide》,今天是第71天,我们正在讲解CUDA 动态并行,希望在接下来的30天里,您可以...

1132

扫码关注云+社区