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

com.app.common.cluster.ZkCluster Maven / Gradle / Ivy

package com.app.common.cluster;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

import org.I0Itec.zkclient.IZkChildListener;
import org.I0Itec.zkclient.IZkDataListener;
import org.apache.commons.lang3.StringUtils;
import org.apache.zookeeper.CreateMode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.app.common.encrypt.RSA;
import com.app.common.utils.StringUtil;
import com.app.common.zk.ZookeeperClient;
import com.gw.common.utils.Consts;

/**
 * 基于zookeeper实现集群模式
 * 
 * @author deshuai.kong
 *
 */
public class ZkCluster extends AbstractCluster {
	private final Logger logger = LoggerFactory.getLogger(this.getClass());
	private String root = "/MDTService";
	public static ZookeeperClient zk = null;
	private String zkHosts;

	private ConcurrentHashMap chm = new ConcurrentHashMap<>();

	@Override
	public String getClusterName() {
		return "ZK";
	}

	@Override
	public synchronized void startServer(ServerInfo serverInfo) throws Exception {
		if (serverInfo.isRegisterEnable()) {
			createZkClient(serverInfo);
		}
		createServerNode(serverInfo, true);
	}

	private synchronized void createZkClient(ServerInfo serverInfo) {
		logger.info("createZkClient:{},{}", serverInfo, serverInfo.atts);
		if (zk == null) {
			HashMap hm = serverInfo.atts;
			if (hm != null && hm.size() > 0) {
				zkHosts = hm.get("Cluster.Zookeeper.Hosts") + "";
				String zkUserName = null;
				String zkPassword = null;
				if (hm.containsKey("Cluster.Zookeeper.UserName")) {
					zkUserName = hm.get("Cluster.Zookeeper.UserName") + "";
				}
				if (hm.containsKey("Cluster.Zookeeper.Password")) {
					zkPassword = hm.get("Cluster.Zookeeper.Password") + "";
				}
				if (hm.containsKey("Cluster.Zookeeper.PrivateKey")) {
					String privateKey = hm.get("Cluster.Zookeeper.PrivateKey") + "";
					if(StringUtil.isNotBlank(privateKey)) {
						try {
							zkPassword=RSA.decrypt(zkPassword, privateKey);
						} catch (Exception e) {
							logger.error("decrypt:{},{},{}",zkPassword,privateKey,e);
						}
					}
				}
				zk = new ZookeeperClient(zkHosts, zkUserName, zkPassword);
			}
		}
	}

	private IZkChildListener zkChildListener = new IZkChildListener() {

		@Override
		public void handleChildChange(String parentPath, List currentChilds) throws Exception {
			try {

				int index = parentPath.lastIndexOf("/");
				String sName = parentPath.substring(index + 1, parentPath.length());
				logger.info("handleChildChange:{},{}", parentPath, sName);
				// client
				List lt = getServerInfo(sName, parentPath, currentChilds);
				for (ServerInfo serverInfo : lt) {
					logger.info("getServerInfo1:{}", serverInfo);
				}
				IClusterClientListener cc = chmClusterClient.get(sName);
				if (cc != null) {
					logger.info("onClustChange:{}", sName);
					cc.onClustChange(lt);
				}
				// server
				ServerInfo serverInfo = chm.get(sName);
				if (serverInfo != null) {
					if ("1".equals(serverInfo.getStat())) {
						boolean isStop = true;
						if(lt.size()==0) {
							boolean flag=createServerNode(serverInfo, false);
							if(flag) {
								return;
							}

						}
						for (String name : currentChilds) {
							String sTempPathNode = parentPath + "/" + name;
							String content = zk.readData(sTempPathNode) + "";
							ServerInfo si = getServerInfoByNodeInfo(content);
							si.setSeqName(name);
							si.setName(sName);
							if (si != null) {
								if (si.getHost().equals(serverInfo.getHost()) && si.getPort() == serverInfo.getPort()
										&& "1".equals(serverInfo.getStat())) {
									isStop = false;
								}
							}
						}
						if (isStop) {
							serverInfo.setStat("0");
							serverInfo.setSeqName("");
							stop(serverInfo);
						}
					}
					createServerNode(serverInfo, false);
				}
			} catch (Exception e) {
				logger.error("handleChildChange", e);
			}

		}

	};

	private List getServerInfo(String serverName, String parentPath, List currentChilds) {
		List lt = new ArrayList();
		for (String name : currentChilds) {
			String sTempPathNode = parentPath + "/" + name;
			String content = zk.readData(sTempPathNode) + "";
			logger.info("currentChilds:{},{},{}", sTempPathNode, name, content);
			ServerInfo si = getServerInfoByNodeInfo(content);
			if (si != null && "1".equals(si.getStat())) {
				si.setSeqName(name);
				si.setName(serverName);
				lt.add(si);
			}
		}
		return lt;
	}

	IZkDataListener zkDataListener = new IZkDataListener() {

		@Override
		public void handleDataDeleted(String dataPath) throws Exception {
			logger.info("handleDataDeleted:" + dataPath);
			List lt = new ArrayList();
			int index = dataPath.lastIndexOf("/");
			String sName = dataPath.substring(index + 1, dataPath.length());
			IClusterClientListener cc = chmClusterClient.get(sName);
			if (cc != null) {
				logger.info("onClustChange:{}", sName);
				cc.onClustChange(lt);
			}
		}

		@Override
		public void handleDataChange(String dataPath, Object data) throws Exception {
			logger.info("handleDataChange:" + dataPath + "," + data);
			List lt = new ArrayList();
			int index = dataPath.lastIndexOf("/");
			String sName = dataPath.substring(index + 1, dataPath.length());
			String content = data + "";
			ServerInfo si = getServerInfoByNodeInfo(content);
			if (si != null && "1".equals(si.getStat())) {
				si.setSeqName(sName);
				si.setName(sName);
				lt.add(si);
			}
			for (ServerInfo serverInfo : lt) {
				logger.info("getServerInfo:{}", serverInfo);
			}
			IClusterClientListener cc = chmClusterClient.get(sName);
			if (cc != null) {
				logger.info("onClustChange:{}", sName);
				cc.onClustChange(lt);
			}
		}
	};

	private  boolean createServerNode(ServerInfo serverInfo, boolean isFrist) {
		boolean flag = false;
		if (!serverInfo.isRegisterEnable()) {
			start(serverInfo);// 拉起服务
			return true;
		}

		if (!zk.exists(root)) {
			zk.create(root, "", CreateMode.PERSISTENT);// 创建持久根节点
		}

		String sPathNode = root + "/" + serverInfo.getName();
		if (!zk.exists(sPathNode)) {
			String data = ServerInfo.TYPE[serverInfo.getType()];
			zk.create(sPathNode, data, CreateMode.PERSISTENT);// 创建持久服务节点
		}
		if (isFrist) {
			zk.subscribeChildChanges(sPathNode, zkChildListener);
			chm.put(serverInfo.getName(), serverInfo);

		}
		boolean isCreateServerNode = true;
		if (!StringUtils.isEmpty(serverInfo.getSeqName())) {
			String sTempPathNode = sPathNode + "/" + serverInfo.getSeqName();
			if (zk.exists(sTempPathNode)) {
				isCreateServerNode = false;
			} else {
				serverInfo.setStat("0");
				serverInfo.setSeqName("");
			}
		}
		if (isCreateServerNode) {

			String sTempPathNode = sPathNode + "/" + serverInfo.getName();

			try {
				if (!zk.exists(sTempPathNode)) {
					CreateMode cm = CreateMode.EPHEMERAL_SEQUENTIAL;
					if (serverInfo.getType() == (ServerInfo.TYPE_STANDBY)) {// 主备机模式
						cm = CreateMode.EPHEMERAL;
					}
					if (serverInfo.getType() == (ServerInfo.TYPE_STANDBY)) {
						String data = String.format("Host:%s,Port:%s,Stat:%s", serverInfo.getHost(),
								serverInfo.getPort(), "0");
						logger.info("zk.create:{}:{}", sTempPathNode,data);
						String seqName = zk.create(sTempPathNode, data, cm);// 创建临时服务节点
						seqName = seqName.replace(sPathNode + "/", "");
						serverInfo.setSeqName(seqName);
						serverInfo.setStat("1");
						start(serverInfo);// 拉起服务
						sTempPathNode = sPathNode + "/" + serverInfo.getSeqName();
						data = String.format("Host:%s,Port:%s,Stat:%s", serverInfo.getHost(), serverInfo.getPort(),
								"1");
						zk.writeData(sTempPathNode, data);// 激活服务
						logger.info("zk.writeData:{}:{}", sTempPathNode,data);

					} else {
						if (isFrist) {
							start(serverInfo);// 拉起服务
							String data = String.format("Host:%s,Port:%s,Stat:%s", serverInfo.getHost(),
									serverInfo.getPort(), "1");
							logger.info("zk.create:{}:{}", sTempPathNode,data);
							String seqName = zk.create(sTempPathNode, data, cm);// 创建临时服务节点
							seqName = seqName.replace(sPathNode + "/", "");
							serverInfo.setSeqName(seqName);
							serverInfo.setStat("1");
						}
					}
					flag = true;
				}

			} catch (Exception e) {

				logger.error("", e);
			}

		}
		return flag;
	}

	private ServerInfo getServerInfoByNodeInfo(String content) {
		ServerInfo si = null;

		String[] strs = content.split(",");
		if (strs.length > 1) {
			si = new ServerInfo();
		}
		for (String str : strs) {
			String[] strs2 = str.split(":");
			if (strs2.length == 2) {
				if ("Stat".equals(strs2[0])) {
					si.setStat(strs2[1]);
				}
				if ("Host".equals(strs2[0])) {
					si.setHost(strs2[1]);
				}
				if ("Port".equals(strs2[0])) {
					si.setPort(Integer.parseInt(strs2[1]));
				}

			}
		}
		return si;
	}

	// client
	private ConcurrentHashMap chmClusterClient = new ConcurrentHashMap<>();
	private ConcurrentHashMap chmZkChild = new ConcurrentHashMap<>();

	@Override
	public void startClient(ServerInfo serverInfo, IClusterClientListener clusterListener) {
		createZkClient(serverInfo);
		chmClusterClient.put(serverInfo.getName(), clusterListener);
		listenerServerNode(serverInfo);
	}

	private void listenerServerNode(ServerInfo serverInfo) {
		logger.info("{} listenerServerNode ", serverInfo.getName());
		if (zk == null) {
			logger.info("{} zk is null ", serverInfo.getName());
			return;
		}
		if (!zk.exists(root)) {
			zk.create(root, "", CreateMode.PERSISTENT);// 创建持久根节点
		}

		String sPathNode = root + "/" + serverInfo.getName();
		if (!zk.exists(sPathNode)) {
			String data = ServerInfo.TYPE[serverInfo.getType()];
			zk.create(sPathNode, data, CreateMode.PERSISTENT);// 创建持久服务节点
		}
		if (!chmZkChild.containsKey(sPathNode)) {
			if (serverInfo.getType() == (ServerInfo.TYPE_STANDBY)) {
				zk.subscribeDataChanges(sPathNode + "/" + serverInfo.getName(), zkDataListener);
			} else {
				zk.subscribeChildChanges(sPathNode, zkChildListener);
			}
		}

	}

	public List getServerInfo(ServerInfo serverInfo) {
		List slt = new ArrayList();
		if (zk != null) {
			createZkClient(serverInfo);
			String sPathNode = root + "/" + serverInfo.getName();
			List lt = zk.getChildren(sPathNode);
			List siLt = getServerInfo(serverInfo.getName(), sPathNode, lt);
			for (ServerInfo si : siLt) {
                if ("1".equals(si.getStat()) && StringUtil.isNotBlank(si.getHost()) && !Consts.ServerInfo.equals(si.toString())) {
                    slt.add(si);
                }
				logger.info("getServerInfo:{}", si);
			}
		}
		return slt;
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy