package com.autonavi.tinfo.traffic.zookeeper;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import org.apache.zookeeper.Watcher.Event.KeeperState;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.github.zkclient.IZkChildListener;
import com.github.zkclient.IZkStateListener;
import com.github.zkclient.ZkClient;

public class DistributedZookeeper {
    private static final Logger logger = LoggerFactory.getLogger(DistributedZookeeper.class);
    private Lock lock = new ReentrantLock();// 锁对象
    private int sessionTimeout;
    private int connectionTimeout;
    private String zkServerList;
    // private String zkServerDir = "tmc-city-root-path";
    private String subNode = "tmclr";
    private String curPath;
    private ZkClient zkClient;
    private String[] resourcePath;
    private String zookeeperPath;

    public String getZookeeperPath() {
        return zookeeperPath;
    }

    public void setZookeeperPath(String zookeeperPath) {
        this.zookeeperPath = zookeeperPath;
    }

    private ClassPathXmlApplicationContext context = null;

    private void start() {
        if (context == null) {
            context = new ClassPathXmlApplicationContext(resourcePath);
        }
    }

    private void destroy() {
        if (context != null) {
            // context.registerShutdownHook();

            logger.info("destroyed current application!!!");
            context.stop();
            context.close();
            context.destroy();
            context.registerShutdownHook();
            context = null;
        }
    }

    public void connect() throws Exception {

        if (this.zkClient != null) {
            this.zkClient.close();
        }
        this.zkClient = new ZkClient(zkServerList, sessionTimeout, connectionTimeout);

        if (!zkClient.exists(zookeeperPath)) {
            zkClient.createPersistent(zookeeperPath, null);
        }
        if (curPath == null) {
            curPath = zkClient.createEphemeralSequential(zookeeperPath + "/" + subNode, "monitor".getBytes());
        }

        try {
            startWatchingTopicStatus();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            logger.error(e.getMessage(), e);
            logger.error("error occurs during sync data from zk");
            System.exit(0);
        }
        Thread.sleep(2000);// */
        handleMonitorNodeChange();
    }

    public void startWatchingTopicStatus() {
        ZkTopicStatusListener topicEventListener = new ZkTopicStatusListener();
        ZkConnectedStatusListener connectedStatusListener = new ZkConnectedStatusListener();
        try {
            zkClient.subscribeChildChanges(zookeeperPath, topicEventListener);
            zkClient.subscribeStateChanges(connectedStatusListener);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            }
            startWatchingTopicStatus();
        }

    }

    public void handleMonitorNodeChange() throws Exception {
        this.lock.lock();
        try {
            if (zkClient == null)
                return;
            if (!zkClient.exists(zookeeperPath)) {
                zkClient.createPersistent(zookeeperPath, null);
            }

            // 确认curPath是否真的是列表中的最小节点
            List<String> childs = zkClient.getChildren(zookeeperPath);
            if (childs == null || childs.size() == 0) {
                // 创建子节点
                curPath = zkClient.createEphemeralSequential(zookeeperPath + "/" + subNode, "monitor".getBytes());
                childs = zkClient.getChildren(zookeeperPath);

            }
            Collections.sort(childs);

            String thisNode = curPath.substring((zookeeperPath + "/").length());
            int index = childs.indexOf(thisNode);
            if (index < 0) {
                curPath = zkClient.createEphemeralSequential(zookeeperPath + "/" + subNode, "monitor".getBytes());
                childs = zkClient.getChildren(zookeeperPath);
                Collections.sort(childs);
                thisNode = curPath.substring((zookeeperPath + "/").length());
                index = childs.indexOf(thisNode);
            }

            if (index == 0) {
                // 确实是最小节点
                start();
            } else {
                destroy();
            }
        } finally {
            this.lock.unlock();
        }
    }

    class ZkTopicStatusListener implements IZkChildListener {

        @Override
        public void handleChildChange(String parentPath, List<String> currentChilds) throws Exception {
            handleMonitorNodeChange();
        }
    }

    class ZkConnectedStatusListener implements IZkStateListener {

        @Override
        public void handleStateChanged(KeeperState state) throws Exception {
            // TODO Auto-generated method stub ConnectedReadOnly
            if (state.equals(KeeperState.SyncConnected) || state.equals(KeeperState.ConnectedReadOnly)) {
                System.out.println("zookeeper start to be connected");
                handleMonitorNodeChange();
            } else if (state.equals(KeeperState.Disconnected)) {
                destroy();
            }
        }

        @Override
        public void handleNewSession() throws Exception {
            // TODO Auto-generated method stub
        }

    }

    public void stop() {
        destroy();
        if (zkClient == null) {
            logger.warn("cannot shutdown already shutdown topic event watcher.");
            return;
        }
        // stopWatchingTopicEvents();
        zkClient.close();
        zkClient = null;
    }

    public void setZkServerList(String zkServerList) {
        this.zkServerList = zkServerList;
    }

    public int getSessionTimeout() {
        return sessionTimeout;
    }

    public void setSessionTimeout(int sessionTimeout) {
        this.sessionTimeout = sessionTimeout;
    }

    public int getConnectionTimeout() {
        return connectionTimeout;
    }

    public void setConnectionTimeout(int connectionTimeout) {
        this.connectionTimeout = connectionTimeout;
    }

    public String[] getResourcePath() {
        return resourcePath;
    }

    public void setResourcePath(String[] resourcePath) {
        this.resourcePath = resourcePath;
    }

    public static void main(String[] args) throws Exception {
        DistributedZookeeper statusMonitor = new DistributedZookeeper();
        try {
            if (args.length < 5) {
                logger.warn("incomplete parameters.");
                System.exit(0);
            }

            // statusMonitor.setZkServerList("10.17.133.73:2181,10.17.133.73:2182,10.17.133.73:2183");
            // statusMonitor.setConnectionTimeout(5000);
            // statusMonitor.setSessionTimeout(5000);
            // statusMonitor.setResourcePath(args);

            statusMonitor.setZkServerList(args[0]);
            statusMonitor.setConnectionTimeout(Integer.valueOf(args[1]));
            statusMonitor.setSessionTimeout(Integer.valueOf(args[2]));
            statusMonitor.setZookeeperPath(args[3]);
            statusMonitor.setResourcePath(Arrays.copyOfRange(args, 4, args.length));

            statusMonitor.connect();

            Executors.newSingleThreadExecutor().awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);
        } catch (Exception e) {
            logger.error(e.toString(), e);
            statusMonitor.stop();
            System.exit(0);
        } catch (OutOfMemoryError e) {
            logger.error(e.toString(), e);
            statusMonitor.stop();
            System.exit(0);
        }
    }

}

#!/bin/sh
#zookeeper address
zkAddress=100.69.209.30:2181,100.69.207.28:2181,100.69.193.87:2181
#connection timeout  in  Millseconds
connectTimeOut=60000
#session timeout  in  Millseconds
sessionTimeOut=60000
zookeeperPath="/tmc-city-path-aone"

x=`echo $0 | grep "^/"`
if test "${x}"; then
    dir=`dirname $0`
else
    pwdv=`pwd`
    dir=`dirname ${pwdv}/$0`
fi
dir=`readlink -m $dir`
echo "app location : "$dir

run="nohup /opt/taobao/java/bin/java  -Xms2G  -Xmx6G -Duser.dir=$dir/..  -cp ${dir}/../etc:${dir}/../lib/* com.autonavi.tinfo.traffic.zookeeper.DistributedZookeeper $zkAddress $connectTimeOut $sessionTimeOut $zookeeperPath classpath:ctx/**/*.xml"
log="nohup.out"
app_dir=`echo $dir|awk -F'/' '{print $(NF-1)}'`
len=`expr ${#app_dir} / 3`
app_dir_blur=`expr substr $app_dir 1 $len`
shutdown="kill `ps -ef|grep /opt/taobao/java/bin/java  |grep $dir| awk '{print $2}'`"
sd_rb="kill `ps -ef|grep /opt/taobao/java/bin/java  |grep $app_dir_blur| awk '{print $2}'`"

stopApp() {
    echo "starting stop ..."
    pid=`ps -ef|grep /opt/taobao/java/bin/java |grep $dir| awk '{print $2}'`
    echo $pid
    if [ ! $pid ]; then
        echo "not find process to kill"
    else
        kill -9 $pid
        echo "kill -9 $pid successfully"
    fi
}

case $1 in
    start)
        $run >> $log 2>&1 &
        chmod 744  $log
        ;;
    stop)
        #$shutdown
        stopApp
        ;;
    restart)
        $shutdown &&
        $run >> $log 2>&1 &
        ;;
    rb)
        $sd_rb &&
        $run >> $log 2>&1 &
        ;;
    *)
        echo "usage: run.sh [start|stop|restart]"
esac

posted on 2016-06-20 19:44  xuxu_dragon  阅读(609)  评论(0编辑  收藏  举报