java - 用于 Java/Spring 配置的 ZooKeeper?

标签 java spring service configuration apache-zookeeper

是否有任何使用 Apache ZooKeeper 用于分发 Java 应用程序配置(尤其是 Spring 服务)的有据可查的用例?

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

更新

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

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

    }

}

最佳答案

你应该考虑 Spring Cloud Config:

http://projects.spring.io/spring-cloud/

Spring Cloud Config Centralized external configuration management backed by a git repository. The configuration resources map directly to Spring Environment but could be used by non-Spring applications if desired.

这里有源代码:

https://github.com/spring-cloud/spring-cloud-config

此处的示例应用程序:

https://github.com/spring-cloud/spring-cloud-config/blob/master/spring-cloud-config-sample/src/main/java/sample/Application.java

关于java - 用于 Java/Spring 配置的 ZooKeeper?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9940476/

相关文章:

java - Tomcat:如何在 Netbeans 中设置 Java 系统属性?

java - 处理异常的构造函数

java - spring websockets - 是否可以向离线用户发送消息?

java - 如何在 DEBUG View 中探索服务器的 Spring 上下文

powershell - PowerShell 可以编写 SQL Server Reporting Services RDL 文件的脚本吗?

java - ActiveMQ持久化: some troubles with AMQ Message Store

java - 应用程序状态 : Static variables or Setters and Getters in JAVA

spring - 如何在 spring mvc 3 中使用 jdbcTemplate 返回结果集的预准备语句?

android - ExoPlayer 背景音频和前景视频?

java - 服务效率