开源配置管理工具config-toolkit 使用心得

这是本人第一次写博,有不当之处敬请指正html

首先感谢config-toolkit 开发者 wangyuxuanjava

因为分布式项目修改某个值,就须要全部应用中的配置均须要修改, 因此项目须要将配置集中管理,在wangyuxuan大哥的帮助下,顺利完成了config-toolkit与项目集成,本文是我的在集成config-toolkit时的心得node

config-toolkit 下载地址:https://github.com/dangdangdotcom/config-toolkit 在此地址中做者介绍了config-toolkit的做用以及使用python

本文在此基础上进行详细集成说明:git

开发环境:win七、jdk1.六、spring3.二、tomcat七、zookeeper3.3.6github

配置文件类型; *.propertiesweb

本人项目中使用config-toolkit特色:spring

  • 实现配置热更新 (举例; 应用中上传文件的路径须要修改,无需停服务就能够实时更改)
  • 版本控制,支持灰度发布 (举例:多个应用使用不一样的配置,能够快速从测试环境的配置更改到正式环境的配置)

    1、搭建ConfigWeb环境,用于管理ZK中的配置信息

    搭建configweb

    下载config-toolkit,将config-web工程进行打成war包,部署到tomcat7下tomcat

    注:因为config-web使用了鉴权密码,故须要执行如下python程序app

    [python] view plain copy print ?
    1. python -c "import hashlib;print hashlib.sha1('abc').hexdigest();"  
    2.  
    3. # a9993e364706816aba3e25717850c26c9cd0d89d  
    4.  
    5. echo "set /aaa/bbb a9993e364706816aba3e25717850c26c9cd0d89d" |./zkCli.sh -server localhost:2181  
     python -c "import hashlib;print hashlib.sha1('abc').hexdigest();" 
    
     # a9993e364706816aba3e25717850c26c9cd0d89d 
    
     echo "set /aaa/bbb a9993e364706816aba3e25717850c26c9cd0d89d" |./zkCli.sh -server localhost:2181


    因为本人不想执行python程序,故修改源代码AuthDao.java,为了快速进入控制界面,此处请原做者原谅可怜

    1. @Override  
    2. public boolean checkAuth(String nodeName, String password) {  
    3.    LOGGER.debug("Check auth: [{}]", nodeName);  
    4.    String hash = password; //sha1Digest(password);  
    5.      
    6.    boolean isPass = false;  
    7.    try {  
    8.        // 判断节点是否存在  
    9.        Stat stat = getClient().checkExists().forPath(nodeName);  
    10.        System.out.println("--------------------------stat:"+stat);  
    11.        System.out.println("--------------------------stat:"+ stat != null);  
    12.        if (stat != null) {  
    13.            byte[] data = getClient().getData().forPath(nodeName);  
    14.            System.out.println("--------------------------data:"+ data);  
    15.            System.out.println("--------------------------data String:"+ new String(data));  
    16.            System.out.println("--------------------------hash:"+hash);  
    17.            isPass = hash.equals(new String(data));  
    18.            System.out.println("--------------------------isPass:"+ isPass);  
    19.        }  
    20.    } catch (Exception e) {  
    21.        throw Throwables.propagate(e);  
    22.    }  
    23.    return isPass;  
    24. }  
    @Override
    	public boolean checkAuth(String nodeName, String password) {
    		LOGGER.debug("Check auth: [{}]", nodeName);
    		String hash = password; //sha1Digest(password);
    		
    		boolean isPass = false;
    		try {
    			// 判断节点是否存在
    			Stat stat = getClient().checkExists().forPath(nodeName);
    			System.out.println("--------------------------stat:"+stat);
    			System.out.println("--------------------------stat:"+ stat != null);
    			if (stat != null) {
    				byte[] data = getClient().getData().forPath(nodeName);
    				System.out.println("--------------------------data:"+ data);
    				System.out.println("--------------------------data String:"+ new String(data));
    				System.out.println("--------------------------hash:"+hash);
    				isPass = hash.equals(new String(data));
    				System.out.println("--------------------------isPass:"+ isPass);
    			}
    		} catch (Exception e) {
    			throw Throwables.propagate(e);
    		}
    		return isPass;
    	}


    登录config-web界面

    给根节点建立版本号,上传或者建立配置文件

    2、配置管理介绍

    非热更新配置集成

    Spring PlaceholderConfigurer集成

    注:此集成仅支持spring3.2以上版本

    1. <bean id="configFactory" class="com.dangdang.config.service.easyzk.ConfigFactory">  
    2.    <constructor-arg name="connectStr" value="zoo.host1:8181,zoo.host2:8181,zoo.host3:8181" />  
    3.    <constructor-arg name="rootNode" value="/projectx/modulex" />  
    4. </bean>  
    5.  
    6. <bean id="zookeeperSources" class="com.dangdang.config.service.easyzk.support.spring.ZookeeperSourceFactory" factory-method="create">  
    7.    <constructor-arg name="configFactory" ref="configFactory" />  
    8.    <constructor-arg name="nodes">  
    9.        <list>  
    10.            <value>config-group1</value>  
    11.            <value>config-group2</value>  
    12.            <value>config-group3</value>  
    13.        </list>  
    14.    </constructor-arg>  
    15. </bean>  
    16.  
    17. <bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">  
    18.    <property name="order" value="1" />  
    19.    <property name="ignoreUnresolvablePlaceholders" value="true" />  
    20.    <property name="propertySources" ref="zookeeperSources" />  
    21. </bean>  
    <bean id="configFactory" class="com.dangdang.config.service.easyzk.ConfigFactory">
        <constructor-arg name="connectStr" value="zoo.host1:8181,zoo.host2:8181,zoo.host3:8181" />
        <constructor-arg name="rootNode" value="/projectx/modulex" />
    </bean>
    
    <bean id="zookeeperSources" class="com.dangdang.config.service.easyzk.support.spring.ZookeeperSourceFactory" factory-method="create">
        <constructor-arg name="configFactory" ref="configFactory" />
        <constructor-arg name="nodes">
            <list>
                <value>config-group1</value>
                <value>config-group2</value>
                <value>config-group3</value>
            </list>
        </constructor-arg>
    </bean>
    
    <bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
        <property name="order" value="1" />
        <property name="ignoreUnresolvablePlaceholders" value="true" />
        <property name="propertySources" ref="zookeeperSources" />
    </bean>

    集成完毕,使用SPEL读取配置值
    此集成方式不支持热更新,不须要进行热更新的配置建议使用此集成方式

    热更新配置集成

    此方式支持spring3.0以上

    编写config-toolkit.properties

    1. #zookeeper服务地址  
    2. zk.address=10.100.15.173:8900  
    3. #zookeeper节点版本 用于灰度发布  
    4. zk.version=2.0.0  
    #zookeeper服务地址
    zk.address=10.100.15.173:8900 
    #zookeeper节点版本 用于灰度发布
    zk.version=2.0.0

    将configNode交给spring管理,将如下代码copy到spring配置文件

    1. <util:properties id="configToolkitCommon" location="classpath:config-toolkit.properties" />  
    2.    <bean id="configFactory" class="com.dangdang.config.service.easyzk.ConfigFactory">  
    3.        <constructor-arg name="connectStr" value="#{configToolkitCommon['zk.address']}" />  
    4.        <constructor-arg name="rootNode" value="/toolkit" />  
    5.        <constructor-arg name="version" value="#{configToolkitCommon['zk.version']}" />  
    6.    </bean>  
    7.    <bean id="configNode" class="com.dangdang.config.service.easyzk.ConfigNode" factory-bean="configFactory" factory-method="getConfigNode">  
    8.        <constructor-arg name="node" value="helloworld" />  
    9.    </bean>  
    <util:properties id="configToolkitCommon" location="classpath:config-toolkit.properties" />
    	<bean id="configFactory" class="com.dangdang.config.service.easyzk.ConfigFactory">
    		<constructor-arg name="connectStr" value="#{configToolkitCommon['zk.address']}" />
    		<constructor-arg name="rootNode" value="/toolkit" />
    		<constructor-arg name="version" value="#{configToolkitCommon['zk.version']}" />
    	</bean>
    	<bean id="configNode" class="com.dangdang.config.service.easyzk.ConfigNode" factory-bean="configFactory" factory-method="getConfigNode">
    		<constructor-arg name="node" value="helloworld" />
    	</bean>


    将configNode注入到业务bean中

    1. @Component  
    2. public class ExampleBeanWithSpel {  
    3.    @Autowired  
    4.    private ConfigNode configNode;  
    5.  
    6.    public void someMethod() {  
    7.        System.out.println(configNode);  
    8.        System.out.println(configNode.get("passWord"));  
    9.    }  
    10. }  
    @Component
    public class ExampleBeanWithSpel {
    	@Autowired
    	private ConfigNode configNode;
    
    	public void someMethod() {
    		System.out.println(configNode);
    		System.out.println(configNode.get("passWord"));
    	}
    }

    测试热更新结果

    1. ApplicationContext applicationContext;  
    2.                    ExampleBeanWithSpel jdbcTemplate = (ExampleBeanWithSpel)applicationContext.getBean("exampleBeanWithSpel");  
    3.                    jdbcTemplate.someMethod();
相关文章
相关标签/搜索