com.alibaba.otter.manager.biz.monitor.impl.GlobalMonitor.java Source code

Java tutorial

Introduction

Here is the source code for com.alibaba.otter.manager.biz.monitor.impl.GlobalMonitor.java

Source

/*
 * 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.manager.biz.monitor.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import org.apache.commons.lang.exception.ExceptionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.CollectionUtils;

import com.alibaba.otter.manager.biz.config.alarm.AlarmRuleService;
import com.alibaba.otter.manager.biz.config.channel.ChannelService;
import com.alibaba.otter.manager.biz.monitor.AlarmRecovery;
import com.alibaba.otter.manager.biz.monitor.Monitor;
import com.alibaba.otter.shared.arbitrate.ArbitrateManageService;
import com.alibaba.otter.shared.common.model.config.alarm.AlarmRule;
import com.alibaba.otter.shared.common.model.config.alarm.AlarmRuleStatus;
import com.alibaba.otter.shared.common.model.config.channel.ChannelStatus;
import com.alibaba.otter.shared.common.utils.thread.NamedThreadFactory;

/**
 * ???? <br/>
 * http://xxxx/monitor/monitor_trigger.htm?token=otter???otter?????jvm??
 * 
 * @author zebin.xuzb @ 2012-8-23
 * @version 4.1.0
 */
public class GlobalMonitor implements Monitor, InitializingBean, DisposableBean {

    protected static final Logger log = LoggerFactory.getLogger("monitorInfo");
    private static final int DEFAULT_THREADS = 5;

    private int nThreads;
    private boolean needConcurrent = true;
    private boolean recoveryPaused = true;
    private ExecutorService executor;

    private AlarmRuleService alarmRuleService;
    private Monitor pipelineMonitor;

    private ChannelService channelService;
    private ArbitrateManageService arbitrateManageService;
    private AlarmRecovery restartAlarmRecovery;

    @Override
    public void explore() {
        Map<Long, List<AlarmRule>> rules = alarmRuleService.getAlarmRules(AlarmRuleStatus.ENABLE);
        if (!CollectionUtils.isEmpty(rules)) {
            if (needConcurrent) {
                concurrentProcess(rules);
            } else {// 
                serialProcess(rules);
            }
        } else {
            log.warn("no enabled alarm rule at all. Check the rule setting please!");
        }

        // ??
        if (recoveryPaused) {
            List<Long> channelIds = channelService.listAllChannelId();
            if (needConcurrent) {
                concurrentProcess(channelIds);
            } else {// 
                serialProcess(channelIds);
            }
        }
    }

    private void concurrentProcess(Map<Long, List<AlarmRule>> rules) {
        ExecutorCompletionService completionExecutor = new ExecutorCompletionService(executor);
        List<Future> futures = new ArrayList<Future>();
        for (Entry<Long, List<AlarmRule>> entry : rules.entrySet()) {
            final List<AlarmRule> alarmRules = entry.getValue();
            futures.add(completionExecutor.submit(new Callable<Object>() {

                @Override
                public Object call() throws Exception {
                    pipelineMonitor.explore(alarmRules);
                    return null;
                }
            }));
        }

        List<Throwable> exceptions = new ArrayList<Throwable>();
        int index = 0;
        int size = futures.size();
        while (index < size) {
            try {
                Future<?> future = completionExecutor.take();
                future.get();
            } catch (InterruptedException e) {
                exceptions.add(e);
            } catch (ExecutionException e) {
                exceptions.add(e);
            }
            index++;
        }

        if (!exceptions.isEmpty()) {
            StringBuilder sb = new StringBuilder(exceptions.size() + " exception happens in global monitor\n");
            sb.append("exception stack start :\n");
            for (Throwable t : exceptions) {
                sb.append(ExceptionUtils.getStackTrace(t));
            }
            sb.append("exception stack end \n");
            throw new IllegalStateException(sb.toString());
        }
    }

    private void serialProcess(Map<Long, List<AlarmRule>> rules) {
        for (Entry<Long, List<AlarmRule>> entry : rules.entrySet()) {
            List<AlarmRule> alarmRules = entry.getValue();
            pipelineMonitor.explore(alarmRules);
        }
    }

    private void concurrentProcess(List<Long> channelIds) {
        ExecutorCompletionService completionExecutor = new ExecutorCompletionService(executor);
        List<Future> futures = new ArrayList<Future>();
        for (final Long channelId : channelIds) {
            futures.add(completionExecutor.submit(new Callable<Object>() {

                @Override
                public Object call() throws Exception {
                    ChannelStatus status = arbitrateManageService.channelEvent().status(channelId);
                    if (status.isPause()) {
                        restartAlarmRecovery.recovery(channelId);
                    }
                    return null;
                }
            }));
        }

        List<Throwable> exceptions = new ArrayList<Throwable>();
        int index = 0;
        int size = futures.size();
        while (index < size) {
            try {
                Future<?> future = completionExecutor.take();
                future.get();
            } catch (InterruptedException e) {
                exceptions.add(e);
            } catch (ExecutionException e) {
                exceptions.add(e);
            }
            index++;
        }

        if (!exceptions.isEmpty()) {
            StringBuilder sb = new StringBuilder(exceptions.size() + " exception happens in global monitor\n");
            sb.append("exception stack start :\n");
            for (Throwable t : exceptions) {
                sb.append(ExceptionUtils.getStackTrace(t));
            }
            sb.append("exception stack end \n");
            throw new IllegalStateException(sb.toString());
        }
    }

    private void serialProcess(List<Long> channelIds) {
        for (Long channelId : channelIds) {
            ChannelStatus status = arbitrateManageService.channelEvent().status(channelId);
            if (status.isPause()) {
                restartAlarmRecovery.recovery(channelId);
            }
        }
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        nThreads = nThreads <= 0 ? DEFAULT_THREADS : nThreads;
        executor = new ThreadPoolExecutor(nThreads, nThreads, 0, TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<Runnable>(nThreads * 2), new NamedThreadFactory("global monitor", false),
                new ThreadPoolExecutor.CallerRunsPolicy());

    }

    @Override
    public void destroy() throws Exception {
        if (executor != null && !executor.isShutdown()) {
            executor.shutdown();
        }
    }

    @Override
    public void explore(Long... pipelineIds) {
        throw new UnsupportedOperationException("doesn't support right now");
    }

    @Override
    public void explore(List<AlarmRule> rules) {
        throw new UnsupportedOperationException("doesn't support right now");
    }

    // ============== setter ==============
    public void setnThreads(int nThreads) {
        this.nThreads = nThreads;
    }

    public void setNeedConcurrent(boolean needConcurrent) {
        this.needConcurrent = needConcurrent;
    }

    public void setAlarmRuleService(AlarmRuleService alarmRuleService) {
        this.alarmRuleService = alarmRuleService;
    }

    public void setPipelineMonitor(Monitor pipelineMonitor) {
        this.pipelineMonitor = pipelineMonitor;
    }

    public void setChannelService(ChannelService channelService) {
        this.channelService = channelService;
    }

    public void setArbitrateManageService(ArbitrateManageService arbitrateManageService) {
        this.arbitrateManageService = arbitrateManageService;
    }

    public void setRestartAlarmRecovery(AlarmRecovery restartAlarmRecovery) {
        this.restartAlarmRecovery = restartAlarmRecovery;
    }

    public void setRecoveryPaused(boolean recoveryPaused) {
        this.recoveryPaused = recoveryPaused;
    }

}