package com.xiaomi.infra.chronos.zookeeper;
import java.util.Properties;
import java.io.IOException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Like HMaster in HBase, FailoverServer relies on ZooKeeper to implement fault-tolerant system.
* Multiple servers can run concurrently but only one will be the active master, which is able to
* run the business logic. Others have to block until the master znode changes.
*
* @see FailoverWatcher
*/
public class FailoverServer {
private static final Log LOG = LogFactory.getLog(FailoverServer.class);
public static final String BASE_ZNODE = "baseZnode";
public static final String ZK_QUORUM = "zkQuorum";
public static final String SESSION_TIMEOUT = "sessionTimeout";
public static final String CONNECT_RETRY_TIMES = "connectRetryTimes";
public static final String ZK_SECURE = "zkSecure";
public static final String ZK_ADMIN = "zkAdmin";
public static final String JAAS_FILE = "jaasFile";
public static final String KRB5_FILE = "krb5File";
public static final String SERVER_HOST = "serverHost";
public static final String SERVER_PORT = "serverPort";
protected FailoverWatcher failoverWatcher;
/**
* Construct FailoverServer with FailoverWatcher.
*
* @param failoverWatcher the FailoverWatcher object
*/
public FailoverServer(FailoverWatcher failoverWatcher) {
this.failoverWatcher = failoverWatcher;
}
/**
* Construct FailoverServer with properties.
*
* @param properties the properties of FailoverWatcher.
* @throws IOException when error to construct FailoverWatcher
*/
public FailoverServer(Properties properties) throws IOException {
this(new FailoverWatcher(properties));
}
public FailoverWatcher getFailoverWatcher() {
return failoverWatcher;
}
/**
* The main logic of active/backup servers.
*/
public void run() {
LOG.info("The server runs and prepares for leader election");
if (failoverWatcher.blockUntilActive()) {
LOG.info("The server becomes active master and prepare to do business logic");
doAsActiveServer();
}
failoverWatcher.close();
LOG.info("The server exits after running business logic");
}
/**
* The method you should override to do your business logic after becoming active master.
*/
public void doAsActiveServer() {
while (true) {
LOG.info("No business logic, sleep for " + Integer.MAX_VALUE);
try {
Thread.sleep(Integer.MAX_VALUE);
} catch (InterruptedException e) {
LOG.error("Interrupt when sleeping as active master", e);
}
}
}
}