Package com.alibaba.otter.shared.arbitrate.impl.setl.rpc.monitor

Source Code of com.alibaba.otter.shared.arbitrate.impl.setl.rpc.monitor.AbstractProcessListener

/*
* Copyright (C) 2010-2101 Alibaba Group Holding Limited.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.alibaba.otter.shared.arbitrate.impl.setl.rpc.monitor;

import java.util.List;
import java.util.concurrent.locks.ReentrantLock;

import org.apache.commons.lang.ClassUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.CollectionUtils;

import com.alibaba.otter.shared.arbitrate.impl.config.ArbitrateConfigUtils;
import com.alibaba.otter.shared.arbitrate.impl.setl.ArbitrateFactory;
import com.alibaba.otter.shared.arbitrate.impl.setl.ArbitrateLifeCycle;
import com.alibaba.otter.shared.arbitrate.impl.setl.helper.ReplyProcessQueue;
import com.alibaba.otter.shared.arbitrate.impl.zookeeper.ZooKeeperClient;
import com.alibaba.otter.shared.common.utils.zookeeper.ZkClientx;

/**
* 抽取stage处理中一些共性的内容
*
* @author jianghang 2011-9-21 下午02:16:17
* @version 4.0.0
*/
public abstract class AbstractProcessListener extends ArbitrateLifeCycle implements ProcessListener {

    protected static final Logger logger    = LoggerFactory.getLogger(AbstractProcessListener.class);
    protected ZkClientx           zookeeper = ZooKeeperClient.getInstance();
    protected ReplyProcessQueue   replyProcessIds;                                                   // 有响应的processId列表
    protected ReentrantLock       lock      = new ReentrantLock();
    protected ProcessMonitor      processMonitor;

    public AbstractProcessListener(Long pipelineId){
        super(pipelineId);
        // 设置容量,必须大于并行度,这里设置为并行度的10倍,避免因并行度的运行时变化引起问题
        int size = ArbitrateConfigUtils.getParallelism(pipelineId) * 10;
        if (size < 100) {
            size = 100;
        }

        replyProcessIds = new ReplyProcessQueue(size);
        processMonitor = ArbitrateFactory.getInstance(pipelineId, ProcessMonitor.class);
        processMonitor.addListener(this);
        processMonitor.reload(); // 触发一下processChanged
    }

    public void processChanged(List<Long> processIds) {
        // 在运行过程中会出现Termin(rollback/restart/shutdown)等信号,仲裁器会删除当前运行的所有process
        // 因此需要删除之前已满足条件的队列记录,在具体的event处理时还会再对processId再做一次判断,是否已被废弃
        compareReply(processIds);
    }

    /**
     * 阻塞方法,获取对应可以被处理的processId,支持中断处理
     */
    public Long waitForProcess() throws InterruptedException {
        // take和history.put操作非原子,addReply操作时会出现并发问题,同一个processId插入两次
        Long processId = (Long) replyProcessIds.take();
        logger.debug("## {} get reply id [{}]", ClassUtils.getShortClassName(this.getClass()), processId);
        return processId;
    }

    protected synchronized void addReply(Long processId) {
        boolean isSuccessed = replyProcessIds.offer(processId);

        if (isSuccessed) {
            logger.debug("## {} add reply id [{}]", ClassUtils.getShortClassName(this.getClass()), processId);
        } else {
            logger.warn("## {} dup reply id [{}]", ClassUtils.getShortClassName(this.getClass()), processId);
        }
    }

    /**
     * 将当前的符合条件的processIds和当前的reply queue进行校对,剔除不在processIds里的内容
     */
    protected synchronized void compareReply(List<Long> processIds) {
        Object[] replyIds = replyProcessIds.toArray();
        for (Object replyId : replyIds) {
            if (processIds.contains((Long) replyId) == false) { // 判断reply id是否在当前processId列表中
                // 因为存在并发问题,如在执行Listener事件的同时,可能触发了process的创建,这时新建的processId会进入到reply队列中
                // 此时接受到的processIds变量为上一个版本的内容,所以会删除新建的process,导致整个通道被挂住
                if (CollectionUtils.isEmpty(processIds) == false) {
                    Long processId = processIds.get(0);
                    if (processId > (Long) replyId) { // 如果当前最小的processId都大于replyId, processId都是递增创建的
                        logger.info("## {} remove reply id [{}]", ClassUtils.getShortClassName(this.getClass()),
                                    (Long) replyId);
                        replyProcessIds.remove((Long) replyId);
                    }
                }
            }
        }
    }

    public void destory() {
        super.destory();
        logger.info("## destory pipeline[{}] , Listener[{}]", getPipelineId(),
                    ClassUtils.getShortClassName(this.getClass()));

        processMonitor.removeListener(this);
        replyProcessIds.clear();
    }

}
TOP

Related Classes of com.alibaba.otter.shared.arbitrate.impl.setl.rpc.monitor.AbstractProcessListener

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.