ZooKeeper for Java / Spring配置? [英] ZooKeeper for Java/Spring Config?

查看:200
本文介绍了ZooKeeper for Java / Spring配置?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有没有很好记录的Apache ZooKeeper用于分布Java应用程序的配置,特别是Spring服务的使用案例?



像许多云服务用户一样需要更改可变数量Java服务的配置,最好在运行时更改,而不需要重新启动服务。



UPDATE



最后,我写了一些东西,将一个ZooKeeper节点作为属性文件加载,并创建一个 ResourcePropertySource 将它插入到Spring上下文中。注意这不会反映在上下文开始之后ZooKeeper节点的变化。

  public class ZooKeeperPropertiesApplicationContextInitializer实现ApplicationContextInitializer< ConfigurableApplicationContext> {
private static final Logger logger = LoggerFactory.getLogger(ZooKeeperPropertiesApplicationContextInitializer.class);

private final CuratorFramework curator;
private String projectName;
private String projectVersion;

public ZooKeeperPropertiesApplicationContextInitializer()throws IOException {
logger.trace(尝试构造CuratorFramework实例);

RetryPolicy retryPolicy = new ExponentialBackoffRetry(10,100);
curator = CuratorFrameworkFactory.newClient(zookeeper,retryPolicy);
curator.start();
}

/ **
*向应用程序上下文中添加主属性源,从预先存在的ZooKeeper节点
*中填充。
* /
@Override
public void initialize(ConfigurableApplicationContext applicationContext){
logger.trace(尝试向ApplicationContext PropertySources添加ZooKeeper派生的属性);

尝试{
populateProjectProperties();
属性properties = populatePropertiesFromZooKeeper();
PropertiesPropertySource propertySource = new PropertiesPropertySource(zookeeper,properties);
applicationContext.getEnvironment()。getPropertySources()。addFirst(propertySource);

logger.debug(向ApplicationContext PropertySources添加了ZooKeeper派生的属性);
curator.close();
} catch(IOException e){
logger.error(IO错误尝试从ZooKeeper加载属性,e);
throw new IllegalStateException(无法加载ZooKeeper配置);
} catch(Exception e){
logger.error(IO错误尝试从ZooKeeper加载属性,e);
throw new IllegalStateException(无法加载ZooKeeper配置);
} finally {
if(curator!= null& curator.isStarted()){
curator.close();
}
}
}

/ **
*从属性文件填充Maven工件名称和版本,
*应该是在类路径上,通过Maven过滤输入的值。
*
*有一种方法来做这些与清单,但它是一个正确的faff当
*创建阴影uber-jar。
*
* @throws IOException
* /
private void populateProjectProperties()throws IOException {
logger.trace(尝试从属性文件中获取项目名称和版本);

try {
ResourcePropertySource projectProps = new ResourcePropertySource(project.properties);
this.projectName =(String)projectProps.getProperty(project.name);
this.projectVersion =(String)projectProps.getProperty(project.version);
} catch(IOException e){
logger.error(IO错误尝试找到项目名称和版本,以便从ZooKeeper获取属性);
}
}

/ **
*实际加载属性。
*
* @return
* @throws异常
* @throws IOException
* /
private属性populatePropertiesFromZooKeeper()throws Exception,IOException {
logger.debug(尝试从ZooKeeper获取属性);

try {
byte [] bytes = curator.getData()。forPath(/ distributed-config /+ projectName +/+ projectVersion);
InputStream in = new ByteArrayInputStream(bytes);
属性properties = new属性();
property.load(in);
return property; $ {$} $ {$} $ {$} $ {$} $ {$} $ {$} $ {$} $ {
} {
} {
logger.error(无法从ZooKeeper加载应用程序配置项目[{}]:[{}],projectName,projectVersion)
throw e;
}

}

}


解决方案

我上周在James Strachen的Apache Camel演讲中提到,他们使用ZooKeeper作为云中的基于Java的服务器作为配置信息的来源。



我见过Adrian Colyer )在我看来,如果你从一个典型的架构的Spring应用程序开始,我不会看不到你有一个简单的工作改造动态配置更改的顶部。


Are there any well documented use cases of Apache ZooKeeper being used to distribute configuration of Java applications, and in particular Spring services?

Like many users of cloud services I have a requirement to change the configuration of a variable amount of Java services, preferably at run-time without needing to restart the services.

UPDATE

Eventually I ended up writing something that would load a ZooKeeper node as a properties file, and create a ResourcePropertySource and insert it into a Spring context. Note that this will not reflect changes in the ZooKeeper node after the context has started.

public class ZooKeeperPropertiesApplicationContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
    private static final Logger logger = LoggerFactory.getLogger(ZooKeeperPropertiesApplicationContextInitializer.class);

    private final CuratorFramework curator;
    private String projectName;
    private String projectVersion;

    public ZooKeeperPropertiesApplicationContextInitializer() throws IOException {
        logger.trace("Attempting to construct CuratorFramework instance");

        RetryPolicy retryPolicy = new ExponentialBackoffRetry(10, 100);
        curator = CuratorFrameworkFactory.newClient("zookeeper", retryPolicy);
        curator.start();
    }

    /**
     * Add a primary property source to the application context, populated from
     * a pre-existing ZooKeeper node.
     */
    @Override
    public void initialize(ConfigurableApplicationContext applicationContext) {
        logger.trace("Attempting to add ZooKeeper-derived properties to ApplicationContext PropertySources");

        try {
            populateProjectProperties();
            Properties properties = populatePropertiesFromZooKeeper();
            PropertiesPropertySource propertySource = new PropertiesPropertySource("zookeeper", properties);
            applicationContext.getEnvironment().getPropertySources().addFirst(propertySource);

            logger.debug("Added ZooKeeper-derived properties to ApplicationContext PropertySources");
            curator.close();
        } catch (IOException e) {
            logger.error("IO error attempting to load properties from ZooKeeper", e);
            throw new IllegalStateException("Could not load ZooKeeper configuration");
        } catch (Exception e) {
            logger.error("IO error attempting to load properties from ZooKeeper", e);
            throw new IllegalStateException("Could not load ZooKeeper configuration");
        } finally {
            if (curator != null && curator.isStarted()) {
                curator.close();
            }
        }
    }

    /**
     * Populate the Maven artifact name and version from a property file that
     * should be on the classpath, with values entered via Maven filtering.
     * 
     * There is a way of doing these with manifests, but it's a right faff when
     * creating shaded uber-jars.
     * 
     * @throws IOException
     */
    private void populateProjectProperties() throws IOException {
        logger.trace("Attempting to get project name and version from properties file");

        try {
            ResourcePropertySource projectProps = new ResourcePropertySource("project.properties");
            this.projectName = (String) projectProps.getProperty("project.name");
            this.projectVersion = (String) projectProps.getProperty("project.version");
        } catch (IOException e) {
            logger.error("IO error trying to find project name and version, in order to get properties from ZooKeeper");
        }
    }

    /**
     * Do the actual loading of properties.
     * 
     * @return
     * @throws Exception
     * @throws IOException
     */
    private Properties populatePropertiesFromZooKeeper() throws Exception, IOException {
        logger.debug("Attempting to get properties from ZooKeeper");

        try {
            byte[] bytes = curator.getData().forPath("/distributed-config/" + projectName + "/" + projectVersion);
            InputStream in = new ByteArrayInputStream(bytes);
            Properties properties = new Properties();
            properties.load(in);
            return properties;
        } catch (NoNodeException e) {
            logger.error("Could not load application configuration from ZooKeeper as no node existed for project [{}]:[{}]", projectName, projectVersion);
            throw e;
        }

    }

}

解决方案

I was at an Apache Camel talk from James Strachen last week and he mentioned using ZooKeeper under the covers for their Java-based server in the cloud as the source of configuration info.

I've seen a talk from Adrian Colyer (CTO of SpringSource) about runtime config change in Spring, but does Spring support this today?

In my opinion, if you're starting from a typically architected Spring application, I don't see you having an easy job retrofitting dynamic config changes on top of it.

这篇关于ZooKeeper for Java / Spring配置?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆