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

com.alogic.zk.ZKFailoverController Maven / Gradle / Ivy

There is a newer version: 1.6.17
Show newest version
package com.alogic.zk;

import java.util.Collections;
import java.util.List;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.Watcher.Event.EventType;

import com.alogic.ha.FailoverController;
import com.alogic.ha.FailoverListener;
import com.anysoft.util.Properties;
import com.anysoft.util.PropertiesConstants;
import com.anysoft.util.UPath;

/**
 * 基于ZK的Failverover控制器
 * @author yyduan
 *
 * @version 1.6.11.29 [20180510 duanyy] 
* - 优化处理
*/ public class ZKFailoverController extends FailoverController.Abstract implements Runnable,Watcher{ /** * the connector to ZooKeeper */ protected ZooKeeperConnector conn = null; /** * 执行线程池 */ protected static ScheduledThreadPoolExecutor exec = new ScheduledThreadPoolExecutor(1); /** * 定时线程的句柄 */ protected ScheduledFuture future = null; /** * 当前是否active状态 */ protected boolean active = false; /** * 根节点地址 */ protected UPath rootPath = new UPath("/alogic/global/ha"); /** * 监听器 */ protected FailoverListener listener = null; /** * ha锁的所在的路径 */ protected UPath haPath = null; /** * 在ZooKeeper中临时节点名称 */ protected String myNode = null; /** * 要等待的节点 */ protected String waitNode = null; /** * 进程信息 */ protected String process = "${server.ip}:${server.port}"; protected long interval = 5000L; private void detect(){ List allNodes = conn.getChildren(haPath, this, false); Collections.sort(allNodes); if (myNode.equals(allNodes.get(0))){ //我就是最小的节点,取得锁 active(true); }else{ active(false); //找到比我小的节点 waitNode = allNodes.get(Collections.binarySearch(allNodes, myNode) - 1); //订阅等待节点的消息 conn.existPath(haPath.append(waitNode), this, false); } } private void active(boolean b) { if (active){ if (!b){ //active->standby active = b; if (listener != null){ listener.becomeStandby(); } } }else{ if (b){ //standy->active active = b; if (listener != null){ listener.becomeActive(); } } } } @Override public boolean isActive() { return active; } @Override public void start(FailoverListener theListener) { listener = theListener; //保证路径确实存在 conn.makePath(haPath,ZooKeeperConnector.DEFAULT_ACL, CreateMode.PERSISTENT); myNode = conn.create(haPath.append("ha"), process, ZooKeeperConnector.DEFAULT_ACL, CreateMode.EPHEMERAL_SEQUENTIAL, false); myNode = myNode.substring(myNode.lastIndexOf("/") + 1); detect(); future = exec.scheduleWithFixedDelay(this, 1000, interval, TimeUnit.MILLISECONDS); } @Override public void stop() { if (future != null){ future.cancel(false); } conn.delete(haPath.append(myNode), true); conn.disconnect(); active(false); } @Override public void configure(Properties p) { haPath = new UPath(rootPath + "/" + PropertiesConstants.getString(p,"failover.name","default")); conn = new ZooKeeperConnector(p); process = PropertiesConstants.getString(p, "failover.process", process); interval = PropertiesConstants.getLong(p,"failover.interval",interval); } @Override public void run() { if (!conn.isConnected()){ conn.connect(); } boolean exist = conn.existPath(haPath.append(myNode), this, false); if (!exist){ //我的节点都被删除了,可能是前期zk掉过线 myNode = conn.create(haPath.append("ha"), process, ZooKeeperConnector.DEFAULT_ACL, CreateMode.EPHEMERAL_SEQUENTIAL, false); myNode = myNode.substring(myNode.lastIndexOf("/") + 1); } detect(); } @Override public void process(WatchedEvent event) { if (event.getType().equals(EventType.NodeDeleted) && event.getPath().equals(haPath + "/" + waitNode)){ //我等待的节点已经被删除,触发检测 detect(); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy