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

cicada.thrift.zookeeper.ServicePublisherImpl Maven / Gradle / Ivy

There is a newer version: 1.0.6.6
Show newest version
package cicada.thrift.zookeeper;

import java.io.IOException;
import org.apache.curator.utils.ZKPaths;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.Watcher.Event.KeeperState;
import org.apache.zookeeper.ZooDefs.Ids;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.Stat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import cicada.core.RandomUtil;

@Component
@Scope("prototype")
public class ServicePublisherImpl implements ServicePublisher, Watcher, DisposableBean
{
	private static final Logger log = LoggerFactory.getLogger(ServicePublisherImpl.class);

	private static final int repairInterval = 1000 * 10;

	private static final int timeout = 1000 * 10;

	private ZooKeeper _zooKeeper;

	private String _respository;

	private ConnectionFailProcessMode _mode;

	private String _path;

	private String _dataPath;

	private boolean _running;

	@Override
	public void Init(String respository, ConnectionFailProcessMode mode, String path, String data)
	{
		this._respository = respository;
		this._mode = mode;
		if (path == null || path.isEmpty() || !path.substring(0, 1).equals("/"))
		{
			this._path = "/" + path;
		}
		else
		{
			this._path = path;
		}

		this._dataPath = this._path.concat("/").concat(data);
	}

	@Override
	public void publish()
	{
		this._running = true;
		this.StartRepair();
	}

	@Override
	public void cancel()
	{
		this._running = false;
	}

	@SuppressWarnings("deprecation")
	@Override
	public void process(WatchedEvent event)
	{
		if (log.isInfoEnabled())
		{
			log.info(String.format("ZooKeeper 状态发生更改 服务中心地址:%s event.type:%s event.state:%s", this._respository, event.getType(), event.getState()));
		}

		KeeperState state = event.getState();
		if (state != KeeperState.Expired)
		{
			switch (state)
			{
				case Unknown:
					break;
				case Disconnected:
					break;
				case NoSyncConnected:
					break;
				default:
					try
					{
						this.validateExistPath();
					}
					catch (Exception ex)
					{
						logException(ex);
						this.failProcess();
					}
					return;
			}
		}
	}

	private void StartRepair()
	{
		RepairThread repair = new RepairThread();
		Thread thread = new Thread(repair);
		thread.start();
	}

	public class RepairThread implements Runnable
	{
		public void run()
		{
			try
			{
				tryRepair(new Object());
			}
			catch (InterruptedException e)
			{
				String mString = String.format("修复zookeeper出错,%s", e.getMessage());
				log.error(mString, e);
			}
		}
	}

	void tryRepair(Object obj) throws InterruptedException
	{
		log.info(String.format("RPC服务中心%s断开连接,尝试连接", this._respository));
		int count = 0;
		while (this._running)
		{
			if (count > 10)
			{
				log.info(String.format("不能与RPC服务中心%s链接成功,系统将停止自动尝试!", this._respository));
				break;
			}
			try
			{
				this.repairProcess();
				log.info(String.format("已与RPC服务中心%s建立连接", this._respository));
				break;
			}
			catch (Exception ex)
			{
				this.close();
				Thread.sleep(repairInterval);
				log.error(String.format("RPC 建立链接出错:%s,详细信息:%s", ex.getMessage(), ex.getStackTrace()));
			}
			count++;
		}
	}

	private void failProcess()
	{
		ConnectionFailProcessMode mode = this._mode;
		if (mode == ConnectionFailProcessMode.Retry)
		{
			this.StartRepair();
			return;
		}
		if (mode != ConnectionFailProcessMode.Throw)
		{
			return;
		}

		log.error(String.format("与服务中心%s断开连接", this._respository));
	}

	private void repairProcess() throws Exception
	{
		if (this._zooKeeper != null && !this._zooKeeper.getState().isAlive())
		{
			this.close();
			Thread.sleep(120 * 1000);
		}
		try
		{
			if (this._zooKeeper == null)
			{
				this.create();
			}

			delExistsNode();
			ZKPaths.mkdirs(this._zooKeeper, this._path);
			this._zooKeeper.create(this._dataPath, new byte[0], Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
			this.validateExistPath();
		}
		catch (Exception ex)
		{
			throw ex;
		}
	}

	private void validateExistPath() throws KeeperException, InterruptedException, Exception
	{
		if (this._zooKeeper == null || this._zooKeeper.exists(this._dataPath, this) == null)
		{
			throw new Exception("节点不存在");
		}
	}

	private String logException(Exception ex)
	{
		String text;
		if (ex instanceof KeeperException.ConnectionLossException)
		{
			text = String.format("无法连接到服务中心,地址为:%s", this._respository);
		}
		else if (ex instanceof KeeperException.SessionExpiredException)
		{
			text = String.format("连接服务中心时发生超时,地址为:%s", this._respository);
		}
		else
		{
			text = String.format("RPC zookeeper注册节点时出现异常,地址为:%s", this._respository);
		}
		log.error(text);
		return text;
	}

	private void create() throws InterruptedException, IOException
	{
		String[] array = this._respository.split(",");
		String connectString = array[RandomUtil.GetRandomNext(array.length)];
		this._zooKeeper = new ZooKeeper(connectString, timeout, this);
		int num = 10;
		while (!this._zooKeeper.getState().equals(ZooKeeper.States.CONNECTED) && num-- > 1)
		{
			Thread.sleep(1000);
		}
	}

	private void close()
	{
		if (this._zooKeeper == null)
		{
			return;
		}
		try
		{

			this._zooKeeper.close();
			this._zooKeeper = null;
		}
		catch (Exception ex)
		{
			String mString = String.format("关闭zookerper服务出错:%s", ex.getMessage());
			log.error(mString, ex);
		}
	}

	private void delExistsNode() throws KeeperException, InterruptedException
	{
		Stat stat = this._zooKeeper.exists(_dataPath, this);
		if (stat != null)
		{
			this._zooKeeper.delete(_dataPath, stat.getAversion());
		}
	}

	@Override
	public void destroy() throws Exception
	{
		this.close();
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy