開源配置管理工具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();
相關文章
相關標籤/搜索