java 用于 Java/Spring 配置的 ZooKeeper

bluestorm 阅读:556 2023-05-26 13:45:46 评论:0

是否有任何使用 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


标签:zookeeper
声明

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

全民解析

全民解析

关注我们