使用zookeeper解决程序在不同集群之间运行的高可用

来源:互联网 发布:js浏览器后退刷新页面 编辑:程序博客网 时间:2024/06/06 05:56
package enn.cn.util;/** * Created by Administrator on 2017/9/18. */import org.apache.zookeeper.*;import org.apache.zookeeper.data.Stat;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import java.io.IOException;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import java.util.Collections;import java.util.List;import java.util.concurrent.CountDownLatch;public class DistributedLock implements Watcher {    private static int threadId;    private static ZooKeeper zk = null;    private static String selfPath;    private static String waitPath;    private static String LOG_PREFIX_OF_THREAD;    private static final int SESSION_TIMEOUT = 10000;    private static  String GROUP_PATH;    private static  String SUB_PATH;    private static final String CONNECTION_STRING = "host16:2181";    private static Object object;    private static String methodName;    private static final int THREAD_NUM = 1;    //确保连接zk成功;    private CountDownLatch connectedSemaphore = new CountDownLatch(1);    //确保所有线程运行结束;    private static  CountDownLatch threadSemaphore = new CountDownLatch(THREAD_NUM);    private static  Logger log = LoggerFactory.getLogger(DistributedLock.class);    public DistributedLock(int id, String group_path, String sub_path) {        this.threadId = id;        this.GROUP_PATH = group_path;        this.SUB_PATH = sub_path;        LOG_PREFIX_OF_THREAD = "【第" + threadId + "个线程】";    }    /*    *  根据某个对象的名称和方法去执行该方法    *    */    public static void execute() {        Class clazz = object.getClass();        Method m1;        try {            m1 = clazz.getDeclaredMethod(methodName);            m1.invoke(object);        } catch (NoSuchMethodException e) {            // TODO Auto-generated catch block            e.printStackTrace();        } catch (IllegalAccessException e) {            // TODO Auto-generated catch block            e.printStackTrace();        } catch (IllegalArgumentException e) {            // TODO Auto-generated catch block            e.printStackTrace();        } catch (InvocationTargetException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }    }    /**     * 获取锁     *     * @return     */    public  void getLock() throws KeeperException, InterruptedException {        //EPHEMERAL_SEQUENTIAL临时顺序节点:基本特性与临时节点一致,创建节点的过程中,zookeeper会在其名字后自动追加一个单调增长的数字后缀,作为新的节点名        selfPath = zk.create(SUB_PATH, null, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);        log.info(LOG_PREFIX_OF_THREAD + "创建锁路径:" + selfPath);        if (checkMinPath()) {            getLockSuccess();        }    }    /**     * 创建节点     *     * @param path 节点path     * @param data 初始数据内容     * @return     */    public boolean createPath(String path, String data, boolean needWatch) throws KeeperException, InterruptedException {        if (zk.exists(path, needWatch) == null) {            log.info(LOG_PREFIX_OF_THREAD + "节点创建成功, Path: "                    + this.zk.create(path,                    data.getBytes(),                    ZooDefs.Ids.OPEN_ACL_UNSAFE,                    CreateMode.PERSISTENT)                    + ", content: " + data);        }        return true;    }    /**     * 创建ZK连接     *     * @param connectString  ZK服务器地址列表     * @param sessionTimeout Session超时时间     */    public void createConnection(String connectString, int sessionTimeout) throws IOException, InterruptedException {        zk = new ZooKeeper(connectString, sessionTimeout, this);        connectedSemaphore.await();    }    /**     * 获取锁成功     */    public void getLockSuccess() throws KeeperException, InterruptedException {        if (zk.exists(this.selfPath, false) == null) {            log.error(LOG_PREFIX_OF_THREAD + "本节点已不在...");            return;        }        log.info(LOG_PREFIX_OF_THREAD + "获取锁成功!");        execute();        log.info(LOG_PREFIX_OF_THREAD + "删除本节点:" + selfPath);        zk.delete(this.selfPath, -1);        releaseConnection();        threadSemaphore.countDown();    }    /**     * 关闭ZK连接     */    public void releaseConnection() {        if (this.zk != null) {            try {                this.zk.close();            } catch (InterruptedException e) {            }        }        log.info(LOG_PREFIX_OF_THREAD + "释放连接");    }    /**     * 检查自己是不是最小的节点     *     * @return     */    public boolean checkMinPath() throws KeeperException, InterruptedException {        List<String> subNodes = zk.getChildren(GROUP_PATH, false);        Collections.sort(subNodes);        int index = subNodes.indexOf(selfPath.substring(GROUP_PATH.length() + 1));        switch (index) {            case -1: {                log.error(LOG_PREFIX_OF_THREAD + "本节点已不在" + selfPath);                return false;            }            case 0: {                log.info(LOG_PREFIX_OF_THREAD + "子节点中,我在" + selfPath);                return true;            }            default: {                this.waitPath = GROUP_PATH + "/" + subNodes.get(index - 1);                log.info(LOG_PREFIX_OF_THREAD + "获取子节点中,排在我前面的" + waitPath);                try {                    zk.getData(waitPath, true, new Stat());                    return false;                } catch (KeeperException e) {                    if (zk.exists(waitPath, false) == null) {                        log.info(LOG_PREFIX_OF_THREAD + "子节点中,排在我前面的" + waitPath + "已不在");                        return checkMinPath();                    } else {                        throw e;                    }                }            }        }    }    @Override    public void process(WatchedEvent event) {        if (event == null) {            return;        }        Event.KeeperState keeperState = event.getState();        Event.EventType eventType = event.getType();        if (Event.KeeperState.SyncConnected == keeperState) {            if (Event.EventType.None == eventType) {                log.info(LOG_PREFIX_OF_THREAD + "成功连接上ZK服务器");                connectedSemaphore.countDown();            } else if (event.getType() == Event.EventType.NodeDeleted && event.getPath().equals(waitPath)) {                log.info(LOG_PREFIX_OF_THREAD + "收排我前面节点已被删除");                try {                    if (checkMinPath()) {                        getLockSuccess();                    }                } catch (KeeperException e) {                    e.printStackTrace();                } catch (InterruptedException e) {                    e.printStackTrace();                }            }        } else if (Event.KeeperState.Disconnected == keeperState) {            log.info(LOG_PREFIX_OF_THREAD + "与ZK服务器断开连接");        } else if (Event.KeeperState.AuthFailed == keeperState) {            log.info(LOG_PREFIX_OF_THREAD + "权限检查失败");        } else if (Event.KeeperState.Expired == keeperState) {            log.info(LOG_PREFIX_OF_THREAD + "会话失效");        }    }    public static int getThreadId() {        return threadId;    }    public static ZooKeeper getZk() {        return zk;    }    public static String getSelfPath() {        return selfPath;    }    public static String getWaitPath() {        return waitPath;    }    public static String getLogPrefixOfThread() {        return LOG_PREFIX_OF_THREAD;    }    public static int getSessionTimeout() {        return SESSION_TIMEOUT;    }    public static String getGroupPath() {        return GROUP_PATH;    }    public static String getSubPath() {        return SUB_PATH;    }    public static String getConnectionString() {        return CONNECTION_STRING;    }    public static Object getObject() {        return object;    }    public static String getMethodName() {        return methodName;    }    public static int getThreadNum() {        return THREAD_NUM;    }    public CountDownLatch getConnectedSemaphore() {        return connectedSemaphore;    }    public static CountDownLatch getThreadSemaphore() {        return threadSemaphore;    }    public static Logger getLog() {        return log;    }    public static void setThreadId(int threadId) {        DistributedLock.threadId = threadId;    }    public static void setZk(ZooKeeper zk) {        DistributedLock.zk = zk;    }    public static void setSelfPath(String selfPath) {        DistributedLock.selfPath = selfPath;    }    public static void setWaitPath(String waitPath) {        DistributedLock.waitPath = waitPath;    }    public static void setLogPrefixOfThread(String logPrefixOfThread) {        LOG_PREFIX_OF_THREAD = logPrefixOfThread;    }    public static void setGroupPath(String groupPath) {        GROUP_PATH = groupPath;    }    public static void setSubPath(String subPath) {        SUB_PATH = subPath;    }    public static void setObject(Object object) {        DistributedLock.object = object;    }    public static void setMethodName(String methodName) {        DistributedLock.methodName = methodName;    }    public void setConnectedSemaphore(CountDownLatch connectedSemaphore) {        this.connectedSemaphore = connectedSemaphore;    }    public static void setThreadSemaphore(CountDownLatch threadSemaphore) {        DistributedLock.threadSemaphore = threadSemaphore;    }}
package enn.cn.singlepoint;import enn.cn.util.CommonContent;import enn.cn.util.DistributedLock;import org.apache.log4j.Logger;/** * Created by Administrator on 2017/9/20. */public class SingleSupplyOneMain {    private static Logger log = Logger.getLogger(SingleSupplyOneMain.class);    static DistributedLock dc;    public static void main(String[] args) {        new Thread() {            @Override            public void run() {                try {                    dc = new DistributedLock(1,"/singleLocks","/singleLocks/sub");                    dc.createConnection(CommonContent.ZOOKEEPER_HOST, dc.getSessionTimeout());                    //GROUP_PATH不存在的话,由一个线程创建                    //注:如果一个jar包中有多个main方法要调用同一个zookeeper工具类,那么GROUP_PATH路径要不一样,以为一个main方法会创建一个分组                    synchronized (dc.getConnectedSemaphore()) {                        dc.createPath(dc.getGroupPath(), "该节点由线程" + 1 + "创建", true);                    }                    dc.setObject(new TimerManagerTask());                    dc.setMethodName("execTask");                    dc.getLock();                } catch (Exception e) {                    log.error("发布时出现异常:{}", e);                    e.printStackTrace();                }            }        }.start();        try {            dc.getThreadSemaphore().await();            log.info("所有线程运行结束!");        } catch (InterruptedException e) {            e.printStackTrace();        }    }}

原创粉丝点击