All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.foreveross.springboot.dubbo.autoconfigure.SystemPolicyCurator Maven / Gradle / Ivy

package com.foreveross.springboot.dubbo.autoconfigure;

import org.I0Itec.zkclient.IZkChildListener;
import org.I0Itec.zkclient.IZkDataListener;
import org.I0Itec.zkclient.ZkClient;
import org.apache.zookeeper.ZooDefs;
import org.apache.zookeeper.data.ACL;
import org.apache.zookeeper.data.Id;
import org.apache.zookeeper.server.auth.DigestAuthenticationProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Component;

import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * author:wzq
 * date:16-6-28
 * project:ab-system
 * description: 配置管理建设者
 */
@Component
@Profile("prod")
public class SystemPolicyCurator {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    // 需要从配置文件中读取 并做修改
    //  "104.236.154.96:2181,198.199.108.10:2181,159.203.221.126:2181";
    @Value("${zookeeper.address}")
    private String zkAddress = "localhost:2181";

    @Value("${zookeeper.path:/system_policy}")
    private String sysConfig;

    @Value("${zookeeper.acl.admin}")
    private String zkacl_admin; // 需要从配置文件中读取 并做修改

    @Value("${zookeeper.acl.reader}")
    private String zkacl_read; // 需要从配置文件中读取 并做修改
    private String digest = "digest";  // 加密方式,不用修改

    @Value("${app.name}")
    private String type;

    private boolean isSystem = "ab-system".equals(this.type); //  is system
    private String watchPath;


    // 有2中路径 /{sysConfig}  /{sysConfig}/{type},对应不同的权限控制
    private List aclSysConfig;
    private List aclType;

    private static boolean enableAcl = true;
    private ZkClient zkClient;
    private List serviceTypes; // 存储types
    private ConfigChangeListener listener;

    public SystemPolicyCurator() {}

    public void start() {
        if (isSystem) {
            aclSysConfig = new ArrayList();
            aclType = new ArrayList();
            try { // 非system
                // admin 有所有权限 read 有create权限
                aclSysConfig.add(new ACL(ZooDefs.Perms.ALL, new Id(digest, DigestAuthenticationProvider.generateDigest(zkacl_admin))));
                aclSysConfig.add(new ACL(ZooDefs.Perms.CREATE, new Id(digest, DigestAuthenticationProvider.generateDigest(zkacl_read))));

                // admin 有所有权限 read 有read权限
                aclType.add(new ACL(ZooDefs.Perms.ALL, new Id(digest, DigestAuthenticationProvider.generateDigest(zkacl_admin))));
                aclType.add(new ACL(ZooDefs.Perms.READ, new Id(digest, DigestAuthenticationProvider.generateDigest(zkacl_read))));
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            }

            zkClient = new ZkClient(zkAddress);
            if (enableAcl) zkClient.addAuthInfo(digest, zkacl_admin.getBytes());

            _start();
        } else { // 非system

            this.watchPath = sysConfig + "/" + type;
            this.zkClient = new ZkClient(zkAddress);
            // System.out.println("type=" + type);
            // System.out.println("watchPath=" + this.watchPath);
            // ZkClient zkClient = new ZkClient(zkAddress);
            if (enableAcl) zkClient.addAuthInfo(digest, zkacl_read.getBytes()); // acl

            // create config if need
            if (!zkClient.exists(sysConfig)) {
                zkClient.createPersistent(sysConfig);
            }
            if (!zkClient.exists(watchPath)) {
                zkClient.createPersistent(watchPath);
            }

            // listen watchPath
            zkClient.subscribeDataChanges(this.watchPath, new IZkDataListener() {
                public void handleDataChange(String s, Object o) throws Exception {
                    System.out.println("handleDataChange, path=" + s + "Object=" + o.toString());
                }

                public void handleDataDeleted(String s) throws Exception {
                    System.out.println("handleDataDeleted");
                    System.out.println("path=" + s);

                }
            });
        }

        //  testWrite(); // test
    }

    /**
     * 外部实现, 比如mq-demo需要实现配置节点改变和删除的操作
     */
    public interface ConfigChangeListener {
        void onConfigChange(Object newCfg); // 改变配置数据, e.g. mq-demo接收事件

        void onConfigDelete(); // 删除配置节点, e.g. mq-demo接收事件, mq-demo恢复默认值
    }

    public void registerListener(ConfigChangeListener listener) {
        this.listener = listener;
    }


    public void _start() {
        final SystemPolicyCurator self = this;

        // create config if need
        if (!zkClient.exists(sysConfig)) {
            logger.debug("create " + sysConfig);
            zkClient.createPersistent(sysConfig);
        }

        // {sysConfig}管理权限
        if (enableAcl) zkClient.setAcl(sysConfig, aclSysConfig);

        // 开始监听 sysConfig 节点
        zkClient.subscribeDataChanges(sysConfig, new IZkDataListener() {
            public void handleDataChange(String s, Object o) throws Exception {
                logger.debug("subscribeDataChanges handleDataChange, path=" + s + "Object=" + o.toString());
                if (self.listener != null) self.listener.onConfigChange((String) o);
            }

            public void handleDataDeleted(String s) throws Exception {
                logger.debug("subscribeDataChanges handleDataDeleted");
                logger.debug("path=" + s);
                if (self.listener != null) self.listener.onConfigDelete();
            }
        });

        // 开始监听 sysConfig 节点
        // zkClient.subscribeStateChanges(new IZkStateListener() {
        //     public void handleStateChanged(Watcher.Event.KeeperState keeperState) throws Exception {
        //         logger.debug("subscribeStateChanges handleStateChanged");
        //         logger.debug("keeperState=" + keeperState);
        //     }
        //     public void handleNewSession() throws Exception {
        //         logger.debug("subscribeStateChanges handleStateChanged");
        //     }
        //     public void handleSessionEstablishmentError(Throwable throwable) throws Exception {
        //         logger.debug("subscribeStateChanges handleSessionEstablishmentError");
        //     }
        // });

        // 开始监听 sysConfig 节点
        zkClient.subscribeChildChanges(sysConfig, new IZkChildListener() {
            @Override
            public void handleChildChange(String s, List list) throws Exception {
                logger.debug("subscribeChildChanges handleChildChange" + "path=" + s + ",list=" + list.toString());
                self.serviceTypes = list;
                self.childAcl();
            }
        });

        // 测试结果 @ 监听 /sysConfig
        // 添加节点 /sysConfig/rabbit-mq --------------subscribeChildChanges 收到监听事件
        // 删除 /sysConfig/rabbit-mq------------------subscribeChildChanges 收到监听事件
        // 删除 /sysConfig----------------------------subscribeDataChanges 收到监听事件

        initChildNodes();
    }

    private void initChildNodes() {
        // get direct child
        serviceTypes = zkClient.getChildren(sysConfig);
        childAcl();
    }

    /**
     * 获取 所有 types
     *
     * @return List String
     */
    public List getServiceTypes() {
        return Collections.unmodifiableList(serviceTypes);
    }

    /**
     * 设在某个 type 的配置(结点的值)
     *
     * @param type service type
     * @param cfg  new config String
     */
    public void setTypeCfg(String type, Object cfg) {
        String path = getTypePath(type);
        if (!zkClient.exists(path)) {
            zkClient.createPersistent(path, cfg);
        } else {
            zkClient.writeData(path, cfg);
        }
    }

    /**
     * 读取某个 type对应的配置(结点的值)
     *
     * @param type service type
     * @return String new config String
     */
    public Object getTypeCfg(String type) {
        String path = getTypePath(type);
        if (!zkClient.exists(path)) {
            return null;
        }
        return zkClient.readData(path);
    }


    private String getTypePath(String type) {
        return sysConfig + "/" + type;
    }

    /**
     * 对每个child 进行权限控制
     * 规则: system 模块有admin权限
     * 其他每个 type模块 对自己有 read权限
     * TODO 应该只对 "变化" node 做权限修改,而非全部, 提高性能
     */
    private void childAcl() {
        if (!enableAcl) return;
        for (int i = 0; i < serviceTypes.size(); i++) {
            String type = serviceTypes.get(i);
            String thePath = getTypePath(type);
            zkClient.setAcl(thePath, aclType);
        }
    }

//    // 测试 admin write
//    private void testWrite() {
//        while (true) {
//            try {
//                Thread.sleep(2000);
//            } catch (InterruptedException e) {
//                e.printStackTrace();
//            }
//            if (serviceTypes.size() > 0) {
//                String aType = serviceTypes.get(0);
//                String path = sysConfig + "/" + aType;
//                String value = Math.random() + "";
//                logger.debug("write " + path + ", value=" + value);
//                zkClient.writeData(path, value);
//            }
//        }
//    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy