Search in sources :

Example 1 with AsyncWatcher

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;
}
Also used : IZkConnection(org.I0Itec.zkclient.IZkConnection) ZkInterruptedException(org.I0Itec.zkclient.exception.ZkInterruptedException) WatchedEvent(org.apache.zookeeper.WatchedEvent) ZooKeeper(org.apache.zookeeper.ZooKeeper) Stat(org.apache.zookeeper.data.Stat) TreeSet(java.util.TreeSet) ZooKeeperx(com.alibaba.otter.shared.common.utils.zookeeper.ZooKeeperx) KeeperException(org.apache.zookeeper.KeeperException) AsyncWatcher(com.alibaba.otter.shared.arbitrate.impl.zookeeper.AsyncWatcher)

Example 2 with AsyncWatcher

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
    }
}
Also used : WatchedEvent(org.apache.zookeeper.WatchedEvent) StageComparator(com.alibaba.otter.shared.arbitrate.impl.setl.helper.StageComparator) ZooKeeper(org.apache.zookeeper.ZooKeeper) ZkNoNodeException(org.I0Itec.zkclient.exception.ZkNoNodeException) NoNodeException(org.apache.zookeeper.KeeperException.NoNodeException) IZkConnection(org.I0Itec.zkclient.IZkConnection) ZooKeeperx(com.alibaba.otter.shared.common.utils.zookeeper.ZooKeeperx) KeeperException(org.apache.zookeeper.KeeperException) AsyncWatcher(com.alibaba.otter.shared.arbitrate.impl.zookeeper.AsyncWatcher)

Aggregations

AsyncWatcher (com.alibaba.otter.shared.arbitrate.impl.zookeeper.AsyncWatcher)2 ZooKeeperx (com.alibaba.otter.shared.common.utils.zookeeper.ZooKeeperx)2 IZkConnection (org.I0Itec.zkclient.IZkConnection)2 KeeperException (org.apache.zookeeper.KeeperException)2 WatchedEvent (org.apache.zookeeper.WatchedEvent)2 ZooKeeper (org.apache.zookeeper.ZooKeeper)2 StageComparator (com.alibaba.otter.shared.arbitrate.impl.setl.helper.StageComparator)1 TreeSet (java.util.TreeSet)1 ZkInterruptedException (org.I0Itec.zkclient.exception.ZkInterruptedException)1 ZkNoNodeException (org.I0Itec.zkclient.exception.ZkNoNodeException)1 NoNodeException (org.apache.zookeeper.KeeperException.NoNodeException)1 Stat (org.apache.zookeeper.data.Stat)1