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

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

问题描述

是否有任何记录良好的 Apache ZooKeeper 用例用于分发 Java 应用程序的配置,尤其是 Spring 服务的配置?

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

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

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.

更新

最终我写了一些东西来加载一个 ZooKeeper 节点作为一个属性文件,并创建一个 ResourcePropertySource 并将它插入到 Spring 上下文中.请注意,这不会反映上下文启动后 ZooKeeper 节点中的更改.

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;
        }

    }

}

推荐答案

上周我参加了 James Strachen 的 Apache Camel 演讲,他提到在他们的 云端基于 Java 的服务器 作为配置信息的来源.

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.

我看过 Adrian Colyer(SpringSource 的 CTO)关于 Spring 中运行时配置更改的演讲,但 Spring 今天是否支持这个?

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

在我看来,如果您从典型架构的 Spring 应用程序开始,我认为您很难在此基础上改进动态配置更改.

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.

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

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