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

cn.aradin.cluster.zookeeper.starter.handler.ClusterNodeHandler Maven / Gradle / Ivy

package cn.aradin.cluster.zookeeper.starter.handler;

import java.net.Inet4Address;
import java.net.UnknownHostException;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.recipes.cache.PathChildrenCacheEvent;
import org.apache.curator.framework.state.ConnectionState;
import org.apache.zookeeper.CreateMode;

import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;

import cn.aradin.cluster.core.manager.IClusterNodeManager;
import cn.aradin.cluster.core.properties.ClusterProperties;
import cn.aradin.spring.core.enums.RegisterType;
import cn.aradin.zookeeper.boot.starter.handler.INodeHandler;
import cn.aradin.zookeeper.boot.starter.manager.ZookeeperClientManager;
import cn.aradin.zookeeper.boot.starter.properties.Zookeeper;
import cn.aradin.zookeeper.boot.starter.properties.ZookeeperProperties;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class ClusterNodeHandler implements INodeHandler {

	private ClusterProperties clusterProperties;

	private IClusterNodeManager clusterNodeManager;

	private Integer registerRetry = 0;

	public ClusterNodeHandler(ClusterProperties clusterProperties, ZookeeperProperties zookeeperProperties,
			IClusterNodeManager clusterNodeManager) {
		// TODO Auto-generated constructor stub
		if (clusterProperties == null) {
			throw new RuntimeException("Cluster is not config");
		}
		if (!RegisterType.zookeeper.equals(clusterProperties.getRegisterType())) {
			throw new RuntimeException("Cluster is not registed on zookeeper");
		}
		this.clusterProperties = clusterProperties;
		if (zookeeperProperties != null && clusterProperties != null
				&& CollectionUtils.isNotEmpty(zookeeperProperties.getAddresses())) {
			Optional result = zookeeperProperties.getAddresses().stream()
					.filter(zookeeper -> zookeeper.getId().equals(clusterProperties.getZookeeperAddressId())).findAny();
			if (result.isPresent()) {
				this.clusterNodeManager = clusterNodeManager;
				return;
			}
		}
		throw new RuntimeException("Cluster's Zookeeper is not config");
	}

	private Integer rebaseNode(List existNodes, Integer maxNode) {
		if (existNodes == null || existNodes.size() == 0) {
			return 0;
		}
		if (existNodes.size() >= maxNode) {
			throw new RuntimeException("Cluster Node Is OutSize With Nodes " + JSONObject.toJSONString(existNodes));
		}
		List nodes = Lists.newArrayList();
		existNodes.forEach(existNode -> {
			if (StringUtils.isNumeric(existNode)) {
				nodes.add(Integer.parseInt(existNode));
			}
		});
		Collections.sort(nodes);
		for (int i = 0; i < maxNode; i++) {
			if (nodes.size() > i) {
				if (nodes.get(i) != i) {
					return i;
				}
			} else {
				return i;
			}
		}
		throw new RuntimeException("Cluster Node Is OutSize");
	}

	private void registerNode(CuratorFramework client, String nodeName) {
		if (registerRetry++ > 5) {
			registerRetry = 0;
			throw new RuntimeException("Cluster Node Retry Too Many Times");
		}
		Integer index = -1;
		try {
			List childs = client.getChildren().forPath("/" + clusterProperties.getZookeeperAddressId());
			index = rebaseNode(childs, clusterProperties.getMaxNode());
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			throw new RuntimeException(e.getCause());
		}
		try {
			client.create().withMode(CreateMode.EPHEMERAL).forPath(
					"/" + clusterProperties.getZookeeperAddressId() + "/" + String.valueOf(index),
					clusterProperties.getNodeName().getBytes());
			registerRetry = 0;
			clusterNodeManager.setCurrentIndex(index);
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
			if (log.isWarnEnabled()) {
				log.warn("Cluster Register Retry Failed {}", registerRetry);
			}
			registerNode(client, nodeName);
		}
	}

	@Override
	public void init(ZookeeperClientManager clientManager) {
		// TODO Auto-generated method stub
		if (StringUtils.isBlank(clusterProperties.getNodeName())) {
			try {
				if (clusterProperties.isPreferIpAddress()) {
					clusterProperties.setNodeName(Inet4Address.getLocalHost().getHostAddress());
				} else {
					clusterProperties.setNodeName(Inet4Address.getLocalHost().getHostName());
				}
			} catch (UnknownHostException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				throw new RuntimeException(e.getCause());
			}
		}
		if (log.isDebugEnabled()) {
			log.debug("Node Registing, {}", clusterProperties.getNodeName());
		}
		CuratorFramework client = clientManager.getClient(clusterProperties.getZookeeperAddressId());
		try {
			registerNode(client, clusterProperties.getNodeName());
			client.getConnectionStateListenable().addListener(this);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			if (log.isErrorEnabled()) {
				log.error("Node Registed Failed, {}", e.getMessage());
			}
			throw new RuntimeException(e.getCause());
		}
	}

	private boolean supportPath(String path) {
		if (path.contains("/")) {
			path = path.substring(0, path.lastIndexOf("/"));
			if (path.contains("/")) {
				String cluster = path.substring(path.lastIndexOf("/") + 1);
				if (log.isDebugEnabled()) {
					log.debug("Parse Cluster {}", cluster);
				}
				if (clusterProperties.getZookeeperAddressId().equalsIgnoreCase(cluster)) {
					return true;
				}
			}
		}
		return false;
	}

	@Override
	public boolean support(PathChildrenCacheEvent event) {
		// TODO Auto-generated method stub
		String path = event.getData().getPath();
		if (log.isDebugEnabled()) {
			log.debug("Received Event Path {} {}", path, event.getType());
		}
		return supportPath(path);
	}

	@Override
	public void handler(CuratorFramework client, PathChildrenCacheEvent event) {
		// TODO Auto-generated method stub
		try {
			switch (event.getType()) {
			case INITIALIZED:
				if (CollectionUtils.isNotEmpty(event.getInitialData())) {
					Map nodes = new HashMap(clusterProperties.getMaxNode());
					event.getInitialData().forEach(data -> {
						if (supportPath(data.getPath())) {
							String path = data.getPath().substring(data.getPath().lastIndexOf("/") + 1);
							if (StringUtils.isNumeric(path)) {
								nodes.put(Integer.parseInt(path), new String(data.getData()));
							}
						}
					});
					if (log.isDebugEnabled()) {
						log.debug("Find Cluster Nodes {}", JSONObject.toJSONString(nodes));
					}
					clusterNodeManager.nodeInit(nodes);
				}
				break;
			case CHILD_ADDED:
				String node = event.getData().getPath().substring(event.getData().getPath().lastIndexOf("/") + 1);
				if (log.isDebugEnabled()) {
					log.debug("Node Adding {}", node);
				}
				if (StringUtils.isNumeric(node)) {
					clusterNodeManager.nodeAdded(Integer.parseInt(node), new String(event.getData().getData()));
					if (log.isDebugEnabled()) {
						log.debug("Node Added {}", JSONObject.toJSONString(clusterNodeManager.nodeNames()));
					}
				}
				break;
			case CHILD_REMOVED:
				node = event.getData().getPath().substring(event.getData().getPath().lastIndexOf("/") + 1);
				if (log.isDebugEnabled()) {
					log.debug("Node Removing {}", node);
				}
				if (StringUtils.isNumeric(node)) {
					clusterNodeManager.nodeRemoved(Integer.parseInt(node), new String(event.getData().getData()));
					if (log.isDebugEnabled()) {
						log.debug("Node Removed {}", JSONObject.toJSONString(clusterNodeManager.nodeNames()));
					}
				}
				break;
			default:
				break;
			}
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
	}

	@Override
	public void stateChanged(CuratorFramework client, ConnectionState newState) {
		// TODO Auto-generated method stub
		if (newState == ConnectionState.LOST) {
			while (true) {
				try {
					if (client.getZookeeperClient().blockUntilConnectedOrTimedOut()) {
						registerNode(client, clusterProperties.getNodeName());
						log.error("Re Register Succeed {}", clusterProperties.getNodeName());
						break;
					}
				} catch (InterruptedException e) {
					// TODO: log something
					break;
				} catch (Exception e) {
					// TODO: log something
					log.error("Re Register Failed {}", e.getMessage());
				}
			}
		}
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy