
cicada.thrift.zookeeper.ServicePublisherImpl Maven / Gradle / Ivy
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