Zookeeperはパラメータの集中管理を実現する

11099 ワード

前言のアプリケーションプロジェクトにはいくつかのパラメータがあります.一般的には、ローカルプロファイルまたはメモリ変数に格納することを選択できます.クラスタマシンの規模が大きくなく、配置の変更が特に頻繁ではない場合、この2つの方法はいずれもよく解決できる.しかし、クラスタマシンの規模が大きくなり、構成情報がますます頻繁になると、この2つの方法に頼ることはますます困難になる.グローバルパラメータの変更を迅速に行うためには、Zookeeperのいくつかの特性を利用して簡単なパラメータ管理を実現するパラメータの集中的な管理が必要です.
の準備を
jdk:1.7.0_80
zookeeper:3.4.3
curator:2.6.0
spring:3.1.2

Maven導入

    org.springframework
    spring-core
    3.1.2.RELEASE


    org.springframework
    spring-context
    3.1.2.RELEASE


    org.springframework
    spring-beans
    3.1.2.RELEASE


    org.apache.zookeeper
    zookeeper
    3.4.3
    
        
            com.sun.jmx
            jmxri
        
        
            com.sun.jdmk
            jmxtools
        
        
            javax.jms
            jms
        
    


    org.apache.curator
    curator-framework
    2.6.0


    org.apache.curator
    curator-recipes
    2.6.0


目標1./app 1,/app 2のような複数のノードを同時に構成することができる.2.例えば/app 1を構成するだけで、/app 1/modual 1、および/app 1/modual 1/xxx/...のようなサブノードを傍受することができることを望む.3.サーバ起動は、現在指定されている親ノードの下にあるすべてのサブノードデータを取得することができる.4.ノードを追加したり、ノードデータを更新したりするときに動的に通知することができ、コードの中でリアルタイムで最新のデータを取得することができる.5.spring構成ではZookeeperからパラメータを読み出して初期化できます.
実装ZKWatcherクラスは主にZookeeperと接続を確立し、ノードを傍受し、ノードデータを初期化し、ノードデータを更新し、ノードデータを格納するために使用される.
1.同時に、リスニングする複数のノードを構成し、リスニングする必要があるノードを追加する文字列配列をユーザーに提供する.
private String[] keyPatterns;

2.子ノードおよび子ノードをリスニングできる子ノードは、指定したリスニングノードの子ノードを再帰的に取得するために使用されます.
private List listChildren(String path) throws Exception {
    List pathList = new ArrayList();
    pathList.add(path);
    List list = client.getChildren().forPath(path);
    if (list != null && list.size() > 0) {
        for (String cPath : list) {
            String temp = "";
            if ("/".equals(path)) {
                temp = path + cPath;
            } else {
                temp = path + "/" + cPath;
            }
            pathList.addAll(listChildren(temp));
        }
    }
    return pathList;
}

3.サーバー起動初期化ノードデータの上にすべてのノードが再帰的に取得され、すべてのノードデータを取得し、Mapに保存できる.
private Map keyValueMap = new ConcurrentHashMap();
 
if (pathList != null && pathList.size() > 0) {
    for (String path : pathList) {
        keyValueMap.put(path, readPath(path));
        watcherPath(path);
    }
}
 
private String readPath(String path) throws Exception {
    byte[] buffer = client.getData().forPath(path);
    String value = new String(buffer);
    logger.info("readPath:path = " + path + ",value = " + value);
    return value;
}

4.傍受ノードデータの変更PathChildrenCacheを使用してサブノードのCHILD_を傍受するADDED,CHILD_UPDATED,CHILD_REMOVEDイベント:
private void watcherPath(String path) {
    PathChildrenCache cache = null;
    try {
        cache = new PathChildrenCache(client, path, true);
        cache.start(StartMode.POST_INITIALIZED_EVENT);
        cache.getListenable().addListener(new PathChildrenCacheListener() {
 
            @Override
            public void childEvent(CuratorFramework client, PathChildrenCacheEvent event) throws Exception {
                switch (event.getType()) {
                case CHILD_ADDED:
                    logger.info("CHILD_ADDED," + event.getData().getPath());
                    watcherPath(event.getData().getPath());
                    keyValueMap.put(event.getData().getPath(), new String(event.getData().getData()));
                    break;
                case CHILD_UPDATED:
                    logger.info("CHILD_UPDATED," + event.getData().getPath());
                    keyValueMap.put(event.getData().getPath(), new String(event.getData().getData()));
                    break;
                case CHILD_REMOVED:
                    logger.info("CHILD_REMOVED," + event.getData().getPath());
                    break;
                default:
                    break;
                }
            }
        });
    } catch (Exception e) {
        if (cache != null) {
            try {
                cache.close();
            } catch (IOException e1) {
            }
        }
        logger.error("watch path error", e);
    }
}

5.spring構成では、Zookeeperからパラメータを読み込んで初期化するカスタムP r e r t y PlaceholderConfigurerクラスZKPropPlaceholderConfigurerを実装できます.
public class ZKPropPlaceholderConfigurer extends PropertyPlaceholderConfigurer {
 
    private ZKWatcher zkwatcher;
 
    @Override
    protected Properties mergeProperties() throws IOException {
        return loadPropFromZK(super.mergeProperties());
    }
 
    /**
     *  zk        
     * 
     * @param result
     * @return
     */
    private Properties loadPropFromZK(Properties result) {
        zkwatcher.watcherKeys();
        zkwatcher.fillProperties(result);
        return result;
    }
    ......
}

以上の処理により、以下の簡単な構成を使用して目標を達成することができます.


 
    
        
    
 
    
        
    
 
    
        
            ${/a2/m1}
        
        
            ${/a3/m1/v2}
        
        
            ${/a3/m1/v2/t2}
        
    


詳細コードsvnアドレス:http://code.taobao.org/svn/temp-pj/DynamicConfテスト1.まずZookeeperを起動します
zkServer.cmd

2.使用するノードの初期化
public class Create_Node {
 
    static String path = "/a3/m1/v2/t2";
    static CuratorFramework client = CuratorFrameworkFactory.builder()
            .connectString("127.0.0.1:2181").sessionTimeoutMs(5000)
            .retryPolicy(new ExponentialBackoffRetry(1000, 3)).build();
 
    public static void main(String[] args) throws Exception {
        client.start();
        client.create().creatingParentsIfNeeded()
                .withMode(CreateMode.PERSISTENT)
                .forPath(path, "init".getBytes());
    }
}

必要なノードを作成すると、ZKWatcherがリスニングを容易にします.ここでは、以上の構成に基づいて、/a 3/m 1/v 2/t 2と/a 2/m 1/v 1/t 1をそれぞれ初期化します.
3.Mainを起動し、プロファイルの初期化とコード動的取得パラメータをそれぞれ検証する
public class Main {
 
    public static void main(String[] args) throws Exception {
        ApplicationContext context = new ClassPathXmlApplicationContext(new String[] { "spring-config.xml" });
        Person person = (Person) context.getBean("person");
        System.out.println(person.toString());
 
        ZKWatcher zkwatcher = (ZKWatcher) context.getBean("zkwatcher");
        while (true) {
            Person p = new Person(zkwatcher.getKeyValue("/a2/m1"), zkwatcher.getKeyValue("/a3/m1/v2"),
                    zkwatcher.getKeyValue("/a3/m1/v2/t2"));
            System.out.println(p.toString());
 
            Thread.sleep(1000);
        }
    }
}

4.観察ログは同時にパラメータを更新する:
ublic class Set_Data {
 
    static String path = "/a3/m1/v2/t2";
    static CuratorFramework client = CuratorFrameworkFactory.builder().connectString("127.0.0.1:2181")
            .sessionTimeoutMs(5000).retryPolicy(new ExponentialBackoffRetry(1000, 3)).build();
 
    public static void main(String[] args) throws Exception {
        client.start();
        Stat stat = new Stat();
        System.out.println(stat.getVersion());
        System.out.println("Success set node for :" + path + ",new version:"
                + client.setData().forPath(path, "codingo_v2".getBytes()).getVersion());
    }
}

ログの一部は次のとおりです.
2017-08-05 18:04:57 - watcher path : [/a2, /a2/m1, /a2/m1/v1, /a2/m1/v1/t2, /a3/m1, /a3/m1/v2, /a3/m1/v2/t2]
2017-08-05 18:04:57 - readPath:path = /a2,value = 
2017-08-05 18:04:57 - readPath:path = /a2/m1,value = zhaohui
2017-08-05 18:04:57 - readPath:path = /a2/m1/v1,value = 
2017-08-05 18:04:57 - readPath:path = /a2/m1/v1/t2,value = init
2017-08-05 18:04:57 - readPath:path = /a3/m1,value = 
2017-08-05 18:04:57 - readPath:path = /a3/m1/v2,value = nanjing
2017-08-05 18:04:57 - readPath:path = /a3/m1/v2/t2,value = codingo_v10
2017-08-05 18:04:57 - Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@182f4aea: defining beans [zkwatcher,propertyConfigurer,person]; root of factory hierarchy
name = zhaohui,address = nanjing,company = codingo_v10
name = zhaohui,address = nanjing,company = codingo_v10
2017-08-05 18:04:57 - CHILD_ADDED,/a2/m1
2017-08-05 18:04:57 - CHILD_ADDED,/a3/m1/v2
2017-08-05 18:04:57 - CHILD_ADDED,/a2/m1/v1
2017-08-05 18:04:57 - CHILD_ADDED,/a2/m1/v1/t2
2017-08-05 18:04:57 - CHILD_ADDED,/a3/m1/v2/t2
name = zhaohui,address = nanjing,company = codingo_v10
name = zhaohui,address = nanjing,company = codingo_v10
name = zhaohui,address = nanjing,company = codingo_v10
2017-08-05 18:05:04 - CHILD_UPDATED,/a3/m1/v2/t2
name = zhaohui,address = nanjing,company = codingo_v11
name = zhaohui,address = nanjing,company = codingo_v11

総括はZookeeperを通じて1つの簡単なパラメータ化プラットフォームを実現して、もちろん生産の中で多くの最適化の地方を使用したいと思って、本文は1つの構想を提供することにあります;もちろんZookeeperの他にもMQ,分散キャッシュなどを用いてパラメトリックプラットフォームを実現することができる.
個人ブログ:codingo.xyz