use of com.alibaba.otter.shared.arbitrate.impl.zookeeper.AsyncWatcher in project otter by alibaba.
the class DistributedLock method acquireLock.
// ===================== helper method =============================
/**
* 执行lock操作,允许传递watch变量控制是否需要阻塞lock操作
*/
private Boolean acquireLock(final BooleanMutex mutex) {
try {
do {
if (id == null) {
// 构建当前lock的唯一标识
long sessionId = getSessionId();
String prefix = "x-" + sessionId + "-";
// 如果第一次,则创建一个节点
String path = zookeeper.create(root + "/" + prefix, data, CreateMode.EPHEMERAL_SEQUENTIAL);
int index = path.lastIndexOf("/");
id = StringUtils.substring(path, index + 1);
idName = new LockNode(id);
}
if (id != null) {
List<String> names = zookeeper.getChildren(root);
if (names.isEmpty()) {
logger.warn("lock lost with scene:empty list, id[] and node[]", id, idName);
// 异常情况,退出后重新创建一个
unlock();
} else {
// 对节点进行排序
SortedSet<LockNode> sortedNames = new TreeSet<LockNode>();
for (String name : names) {
sortedNames.add(new LockNode(name));
}
if (sortedNames.contains(idName) == false) {
logger.warn("lock lost with scene:not contains ,id[] and node[]", id, idName);
// 异常情况,退出后重新创建一个
unlock();
continue;
}
// 将第一个节点做为ownerId
ownerId = sortedNames.first().getName();
if (mutex != null && isOwner()) {
// 直接更新状态,返回
mutex.set(true);
return true;
} else if (mutex == null) {
return isOwner();
}
SortedSet<LockNode> lessThanMe = sortedNames.headSet(idName);
if (!lessThanMe.isEmpty()) {
// 关注一下排队在自己之前的最近的一个节点
LockNode lastChildName = lessThanMe.last();
lastChildId = lastChildName.getName();
// 异步watcher处理
IZkConnection connection = zookeeper.getConnection();
// zkclient包装的是一个持久化的zk,分布式lock只需要一次性的watcher,需要调用原始的zk链接进行操作
ZooKeeper orginZk = ((ZooKeeperx) connection).getZookeeper();
Stat stat = orginZk.exists(root + "/" + lastChildId, new AsyncWatcher() {
public void asyncProcess(WatchedEvent event) {
if (!mutex.state()) {
// 避免重复获取lock
acquireLock(mutex);
} else {
logger.warn("locked successful.");
}
}
});
if (stat == null) {
// 如果节点不存在,需要自己重新触发一下,watcher不会被挂上去
acquireLock(mutex);
}
} else {
if (isOwner()) {
mutex.set(true);
} else {
logger.warn("lock lost with scene:no less ,id[] and node[]", id, idName);
// 可能自己的节点已超时挂了,所以id和ownerId不相同
unlock();
}
}
}
}
} while (id == null);
} catch (KeeperException e) {
exception = e;
if (mutex != null) {
mutex.set(true);
}
} catch (InterruptedException e) {
interrupt = e;
if (mutex != null) {
mutex.set(true);
}
} catch (Throwable e) {
other = e;
if (mutex != null) {
mutex.set(true);
}
}
if (isOwner() && mutex != null) {
mutex.set(true);
}
return Boolean.FALSE;
}
use of com.alibaba.otter.shared.arbitrate.impl.zookeeper.AsyncWatcher in project otter by alibaba.
the class StageMonitor method syncStage.
// /**
// * 监听process的新增/删除变化,触发process列表的更新
// */
// private void syncStage() {
// // 1. 根据pipelineId构造对应的path
// String path = null;
// try {
// path = StagePathUtils.getProcessRoot(getPipelineId());
// // 2. 监听当前的process列表的变化
// List<String> currentProcesses = zookeeper.getChildren(path, new AsyncWatcher() {
//
// public void asyncProcess(WatchedEvent event) {
// MDC.put(ArbitrateConstants.splitPipelineLogFileKey, String.valueOf(getPipelineId()));
// if (isStop()) {
// return;
// }
//
// // 出现session expired/connection losscase下,会触发所有的watcher响应,同时老的watcher会继续保留,所以会导致出现多次watcher响应
// boolean dataChanged = event.getType() == EventType.NodeDataChanged
// || event.getType() == EventType.NodeDeleted
// || event.getType() == EventType.NodeCreated
// || event.getType() == EventType.NodeChildrenChanged;
// if (dataChanged) {
// syncStage(); // 继续监听
// // initStage(); // 重新更新
// }
// }
// });
//
// // 3. 循环处理每个process
// List<Long> processIds = new ArrayList<Long>();
// for (String process : currentProcesses) {
// processIds.add(StagePathUtils.getProcessId(process));
// }
//
// Collections.sort(processIds); // 排序一下
// // 判断一下当前processIds和当前内存中的记录是否有差异,如果有差异立马触发一下
// if (!currentProcessIds.equals(processIds)) {
// initStage(); // 立马触发一下
// }
// } catch (KeeperException e) {
// syncStage(); // 继续监听
// } catch (InterruptedException e) {
// // ignore
// }
// }
/**
* 监听指定的processId节点的变化
*/
private void syncStage(final Long processId) {
// 1. 根据pipelineId + processId构造对应的path
String path = null;
try {
path = StagePathUtils.getProcess(getPipelineId(), processId);
// 2. 监听当前的process列表的变化
IZkConnection connection = zookeeper.getConnection();
// zkclient包装的是一个持久化的zk,分布式lock只需要一次性的watcher,需要调用原始的zk链接进行操作
ZooKeeper orginZk = ((ZooKeeperx) connection).getZookeeper();
List<String> currentStages = orginZk.getChildren(path, new AsyncWatcher() {
public void asyncProcess(WatchedEvent event) {
MDC.put(ArbitrateConstants.splitPipelineLogFileKey, String.valueOf(getPipelineId()));
if (isStop()) {
return;
}
if (event.getType() == EventType.NodeDeleted) {
// 触发下节点删除
processTermined(processId);
return;
}
// 出现session expired/connection losscase下,会触发所有的watcher响应,同时老的watcher会继续保留,所以会导致出现多次watcher响应
boolean dataChanged = event.getType() == EventType.NodeDataChanged || event.getType() == EventType.NodeDeleted || event.getType() == EventType.NodeCreated || event.getType() == EventType.NodeChildrenChanged;
if (dataChanged) {
// boolean reply = initStage(processId);
// if (reply == false) {// 出现过load后就不需要再监听变化,剩下的就是节点的删除操作
syncStage(processId);
// }
}
}
});
Collections.sort(currentStages, new StageComparator());
List<String> lastStages = this.currentStages.get(processId);
if (lastStages == null || !lastStages.equals(currentStages)) {
// 存在差异,立马触发一下
initProcessStage(processId);
}
} catch (NoNodeException e) {
// 触发下节点删除
processTermined(processId);
} catch (KeeperException e) {
syncStage(processId);
} catch (InterruptedException e) {
// ignore
}
}
Aggregations