Search in sources :

Example 1 with ZooKeeperx

use of com.alibaba.otter.shared.common.utils.zookeeper.ZooKeeperx 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 ZooKeeperx

use of com.alibaba.otter.shared.common.utils.zookeeper.ZooKeeperx in project otter by alibaba.

the class ZooKeeperClientTest method testClient.

@Test
public void testClient() {
    ZkClientx zk = ZooKeeperClient.getInstance();
    // 强制获取zk中的地址信息
    final ZooKeeper zkp = ((ZooKeeperx) zk.getConnection()).getZookeeper();
    ClientCnxn cnxn = (ClientCnxn) ReflectionUtils.getField(clientCnxnField, zkp);
    HostProvider hostProvider = (HostProvider) ReflectionUtils.getField(hostProviderField, cnxn);
    List<InetSocketAddress> serverAddrs = (List<InetSocketAddress>) ReflectionUtils.getField(serverAddressesField, hostProvider);
    want.number(serverAddrs.size()).isEqualTo(3);
    String s1 = serverAddrs.get(0).getAddress().getHostAddress() + ":" + serverAddrs.get(0).getPort();
    want.string(s1).isEqualTo(cluster1);
    Stat stat = new Stat();
    try {
        zkp.getChildren("/otter/channel/304/388", false, stat);
        System.out.println(stat.getCversion());
    } catch (KeeperException e2) {
        // TODO Auto-generated catch block
        e2.printStackTrace();
    } catch (InterruptedException e2) {
        // TODO Auto-generated catch block
        e2.printStackTrace();
    }
    // 测试下session timeout
    final CountDownLatch latch = new CountDownLatch(1);
    new Thread() {

        public void run() {
            try {
                zkp.getChildren("/", false);
            } catch (KeeperException e1) {
                want.fail();
            } catch (InterruptedException e1) {
                want.fail();
            }
            int sessionTimeout = zkp.getSessionTimeout();
            long sessionId = zkp.getSessionId();
            byte[] passwd = zkp.getSessionPasswd();
            try {
                ZooKeeper newZk = new ZooKeeper(cluster1, sessionTimeout, new Watcher() {

                    public void process(WatchedEvent event) {
                    // do nothing
                    }
                }, sessionId, passwd);
                // 用老的sessionId连接上去,进行一次close操作后,让原先正在使用的出现SESSION_EXPIRED
                newZk.close();
            } catch (IOException e) {
                want.fail();
            } catch (InterruptedException e) {
                want.fail();
            }
            latch.countDown();
        }
    }.start();
    try {
        latch.await();
    } catch (InterruptedException e) {
        want.fail();
    }
    zk.getChildren("/");
}
Also used : InetSocketAddress(java.net.InetSocketAddress) StaticHostProvider(org.apache.zookeeper.client.StaticHostProvider) HostProvider(org.apache.zookeeper.client.HostProvider) Watcher(org.apache.zookeeper.Watcher) IOException(java.io.IOException) ZkClientx(com.alibaba.otter.shared.common.utils.zookeeper.ZkClientx) ClientCnxn(org.apache.zookeeper.ClientCnxn) CountDownLatch(java.util.concurrent.CountDownLatch) WatchedEvent(org.apache.zookeeper.WatchedEvent) ZooKeeper(org.apache.zookeeper.ZooKeeper) Stat(org.apache.zookeeper.data.Stat) List(java.util.List) ZooKeeperx(com.alibaba.otter.shared.common.utils.zookeeper.ZooKeeperx) KeeperException(org.apache.zookeeper.KeeperException) Test(org.testng.annotations.Test) BaseOtterTest(com.alibaba.otter.shared.arbitrate.BaseOtterTest)

Example 3 with ZooKeeperx

use of com.alibaba.otter.shared.common.utils.zookeeper.ZooKeeperx in project otter by alibaba.

the class ArbitrateViewServiceImpl method listProcesses.

public List<ProcessStat> listProcesses(Long channelId, Long pipelineId) {
    List<ProcessStat> processStats = new ArrayList<ProcessStat>();
    String processRoot = ManagePathUtils.getProcessRoot(channelId, pipelineId);
    IZkConnection connection = zookeeper.getConnection();
    // zkclient会将获取stat信息和正常的操作分开,使用原生的zk进行优化
    ZooKeeper orginZk = ((ZooKeeperx) connection).getZookeeper();
    // 获取所有的process列表
    List<String> processNodes = zookeeper.getChildren(processRoot);
    List<Long> processIds = new ArrayList<Long>();
    for (String processNode : processNodes) {
        processIds.add(ManagePathUtils.getProcessId(processNode));
    }
    Collections.sort(processIds);
    for (int i = 0; i < processIds.size(); i++) {
        Long processId = processIds.get(i);
        // 当前的process可能会有变化
        ProcessStat processStat = new ProcessStat();
        processStat.setPipelineId(pipelineId);
        processStat.setProcessId(processId);
        List<StageStat> stageStats = new ArrayList<StageStat>();
        processStat.setStageStats(stageStats);
        try {
            String processPath = ManagePathUtils.getProcess(channelId, pipelineId, processId);
            Stat zkProcessStat = new Stat();
            List<String> stages = orginZk.getChildren(processPath, false, zkProcessStat);
            Collections.sort(stages, new StageComparator());
            StageStat prev = null;
            for (String stage : stages) {
                // 循环每个process下的stage
                String stagePath = processPath + "/" + stage;
                Stat zkStat = new Stat();
                StageStat stageStat = new StageStat();
                stageStat.setPipelineId(pipelineId);
                stageStat.setProcessId(processId);
                byte[] bytes = orginZk.getData(stagePath, false, zkStat);
                if (bytes != null && bytes.length > 0) {
                    // 特殊处理zookeeper里的data信息,manager没有对应node中PipeKey的对象,所以导致反序列化会失败,需要特殊处理,删除'@'符号
                    String json = StringUtils.remove(new String(bytes, "UTF-8"), '@');
                    EtlEventData data = JsonUtils.unmarshalFromString(json, EtlEventData.class);
                    stageStat.setNumber(data.getNumber());
                    stageStat.setSize(data.getSize());
                    Map exts = new HashMap();
                    if (!CollectionUtils.isEmpty(data.getExts())) {
                        exts.putAll(data.getExts());
                    }
                    exts.put("currNid", data.getCurrNid());
                    exts.put("nextNid", data.getNextNid());
                    exts.put("desc", data.getDesc());
                    stageStat.setExts(exts);
                }
                if (prev != null) {
                    // 对应的start时间为上一个节点的结束时间
                    stageStat.setStartTime(prev.getEndTime());
                } else {
                    // process的最后修改时间,select
                    stageStat.setStartTime(zkProcessStat.getMtime());
                // await成功后会设置USED标志位
                }
                stageStat.setEndTime(zkStat.getMtime());
                if (ArbitrateConstants.NODE_SELECTED.equals(stage)) {
                    stageStat.setStage(StageType.SELECT);
                } else if (ArbitrateConstants.NODE_EXTRACTED.equals(stage)) {
                    stageStat.setStage(StageType.EXTRACT);
                } else if (ArbitrateConstants.NODE_TRANSFORMED.equals(stage)) {
                    stageStat.setStage(StageType.TRANSFORM);
                // } else if
                // (ArbitrateConstants.NODE_LOADED.equals(stage)) {
                // stageStat.setStage(StageType.LOAD);
                }
                prev = stageStat;
                stageStats.add(stageStat);
            }
            // 添加一个当前正在处理的
            StageStat currentStageStat = new StageStat();
            currentStageStat.setPipelineId(pipelineId);
            currentStageStat.setProcessId(processId);
            if (prev == null) {
                byte[] bytes = orginZk.getData(processPath, false, zkProcessStat);
                if (bytes == null || bytes.length == 0) {
                    // 直接认为未使用,忽略之
                    continue;
                }
                ProcessNodeEventData nodeData = JsonUtils.unmarshalFromByte(bytes, ProcessNodeEventData.class);
                if (nodeData.getStatus().isUnUsed()) {
                    // 跳过该process
                    continue;
                } else {
                    // select操作
                    currentStageStat.setStage(StageType.SELECT);
                    currentStageStat.setStartTime(zkProcessStat.getMtime());
                }
            } else {
                // 判断上一个节点,确定当前的stage
                StageType stage = prev.getStage();
                if (stage.isSelect()) {
                    currentStageStat.setStage(StageType.EXTRACT);
                } else if (stage.isExtract()) {
                    currentStageStat.setStage(StageType.TRANSFORM);
                } else if (stage.isTransform()) {
                    currentStageStat.setStage(StageType.LOAD);
                } else if (stage.isLoad()) {
                    // 已经是最后一个节点了
                    continue;
                }
                // 开始时间为上一个节点的结束时间
                currentStageStat.setStartTime(prev.getEndTime());
            }
            if (currentStageStat.getStage().isLoad()) {
                // load必须为第一个process节点
                if (i == 0) {
                    stageStats.add(currentStageStat);
                }
            } else {
                // 其他情况都添加
                stageStats.add(currentStageStat);
            }
        } catch (NoNodeException e) {
        // ignore
        } catch (KeeperException e) {
            throw new ArbitrateException(e);
        } catch (InterruptedException e) {
        // ignore
        } catch (UnsupportedEncodingException e) {
        // ignore
        }
        processStats.add(processStat);
    }
    return processStats;
}
Also used : NoNodeException(org.apache.zookeeper.KeeperException.NoNodeException) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) ProcessStat(com.alibaba.otter.shared.common.model.statistics.stage.ProcessStat) Stat(org.apache.zookeeper.data.Stat) StageStat(com.alibaba.otter.shared.common.model.statistics.stage.StageStat) StageType(com.alibaba.otter.shared.common.model.config.enums.StageType) ZooKeeperx(com.alibaba.otter.shared.common.utils.zookeeper.ZooKeeperx) ProcessNodeEventData(com.alibaba.otter.shared.arbitrate.model.ProcessNodeEventData) StageComparator(com.alibaba.otter.shared.arbitrate.impl.setl.helper.StageComparator) IZkConnection(org.I0Itec.zkclient.IZkConnection) UnsupportedEncodingException(java.io.UnsupportedEncodingException) EtlEventData(com.alibaba.otter.shared.arbitrate.model.EtlEventData) ZooKeeper(org.apache.zookeeper.ZooKeeper) ProcessStat(com.alibaba.otter.shared.common.model.statistics.stage.ProcessStat) ArbitrateException(com.alibaba.otter.shared.arbitrate.exception.ArbitrateException) StageStat(com.alibaba.otter.shared.common.model.statistics.stage.StageStat) HashMap(java.util.HashMap) Map(java.util.Map) KeeperException(org.apache.zookeeper.KeeperException)

Example 4 with ZooKeeperx

use of com.alibaba.otter.shared.common.utils.zookeeper.ZooKeeperx 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)

Example 5 with ZooKeeperx

use of com.alibaba.otter.shared.common.utils.zookeeper.ZooKeeperx in project otter by alibaba.

the class ArbitrateViewServiceImpl method getNextProcessId.

public Long getNextProcessId(Long channelId, Long pipelineId) {
    String processRoot = ManagePathUtils.getProcessRoot(channelId, pipelineId);
    IZkConnection connection = zookeeper.getConnection();
    // zkclient会将获取stat信息和正常的操作分开,使用原生的zk进行优化
    ZooKeeper orginZk = ((ZooKeeperx) connection).getZookeeper();
    Stat processParentStat = new Stat();
    // 获取所有的process列表
    try {
        orginZk.getChildren(processRoot, false, processParentStat);
        return (Long) ((processParentStat.getCversion() + processParentStat.getNumChildren()) / 2L);
    } catch (Exception e) {
        return -1L;
    }
}
Also used : ZooKeeper(org.apache.zookeeper.ZooKeeper) ProcessStat(com.alibaba.otter.shared.common.model.statistics.stage.ProcessStat) Stat(org.apache.zookeeper.data.Stat) StageStat(com.alibaba.otter.shared.common.model.statistics.stage.StageStat) IZkConnection(org.I0Itec.zkclient.IZkConnection) ZooKeeperx(com.alibaba.otter.shared.common.utils.zookeeper.ZooKeeperx) ArbitrateException(com.alibaba.otter.shared.arbitrate.exception.ArbitrateException) ZkException(org.I0Itec.zkclient.exception.ZkException) KeeperException(org.apache.zookeeper.KeeperException) NoNodeException(org.apache.zookeeper.KeeperException.NoNodeException) UnsupportedEncodingException(java.io.UnsupportedEncodingException)

Aggregations

ZooKeeperx (com.alibaba.otter.shared.common.utils.zookeeper.ZooKeeperx)6 KeeperException (org.apache.zookeeper.KeeperException)6 ZooKeeper (org.apache.zookeeper.ZooKeeper)6 IZkConnection (org.I0Itec.zkclient.IZkConnection)5 Stat (org.apache.zookeeper.data.Stat)5 NoNodeException (org.apache.zookeeper.KeeperException.NoNodeException)4 ArbitrateException (com.alibaba.otter.shared.arbitrate.exception.ArbitrateException)3 ProcessStat (com.alibaba.otter.shared.common.model.statistics.stage.ProcessStat)3 StageStat (com.alibaba.otter.shared.common.model.statistics.stage.StageStat)3 UnsupportedEncodingException (java.io.UnsupportedEncodingException)3 WatchedEvent (org.apache.zookeeper.WatchedEvent)3 StageComparator (com.alibaba.otter.shared.arbitrate.impl.setl.helper.StageComparator)2 AsyncWatcher (com.alibaba.otter.shared.arbitrate.impl.zookeeper.AsyncWatcher)2 ZkException (org.I0Itec.zkclient.exception.ZkException)2 BaseOtterTest (com.alibaba.otter.shared.arbitrate.BaseOtterTest)1 EtlEventData (com.alibaba.otter.shared.arbitrate.model.EtlEventData)1 PositionEventData (com.alibaba.otter.shared.arbitrate.model.PositionEventData)1 ProcessNodeEventData (com.alibaba.otter.shared.arbitrate.model.ProcessNodeEventData)1 StageType (com.alibaba.otter.shared.common.model.config.enums.StageType)1 ZkClientx (com.alibaba.otter.shared.common.utils.zookeeper.ZkClientx)1