Package com.alibaba.otter.manager.biz.remote.impl

Source Code of com.alibaba.otter.manager.biz.remote.impl.StatsRemoteServiceImpl$AvgStat

/*
* 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.remote.impl;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Assert;

import com.alibaba.otter.manager.biz.remote.StatsRemoteService;
import com.alibaba.otter.manager.biz.statistics.delay.DelayStatService;
import com.alibaba.otter.manager.biz.statistics.table.TableStatService;
import com.alibaba.otter.manager.biz.statistics.throughput.ThroughputStatService;
import com.alibaba.otter.shared.common.model.statistics.delay.DelayCount;
import com.alibaba.otter.shared.common.model.statistics.delay.DelayStat;
import com.alibaba.otter.shared.common.model.statistics.table.TableStat;
import com.alibaba.otter.shared.common.model.statistics.throughput.ThroughputStat;
import com.alibaba.otter.shared.common.model.statistics.throughput.ThroughputType;
import com.alibaba.otter.shared.common.utils.thread.NamedThreadFactory;
import com.alibaba.otter.shared.communication.core.CommunicationRegistry;
import com.alibaba.otter.shared.communication.model.statistics.DelayCountEvent;
import com.alibaba.otter.shared.communication.model.statistics.StatisticsEventType;
import com.alibaba.otter.shared.communication.model.statistics.TableStatEvent;
import com.alibaba.otter.shared.communication.model.statistics.ThroughputStatEvent;
import com.google.common.base.Function;
import com.google.common.collect.MapMaker;

/**
* 统计模块远程接口
*
* @author jianghang 2011-10-21 下午03:04:40
* @version 4.0.0
*/
public class StatsRemoteServiceImpl implements StatsRemoteService {

    private static final Logger                            logger       = LoggerFactory.getLogger(StatsRemoteServiceImpl.class);
    private static final int                               DEFAULT_POOL = 10;
    private DelayStatService                               delayStatService;
    private TableStatService                               tableStatService;
    private ThroughputStatService                          throughputStatService;
    private Long                                           statUnit     = 60 * 1000L;                                           //统计周期,默认60秒
    private ScheduledThreadPoolExecutor                    scheduler;
    private Map<Long, AvgStat>                             delayStats;
    private Map<Long, Map<ThroughputType, ThroughputStat>> throughputStats;

    public StatsRemoteServiceImpl(){
        // 注册一下事件处理
        CommunicationRegistry.regist(StatisticsEventType.delayCount, this);
        CommunicationRegistry.regist(StatisticsEventType.tableStat, this);
        CommunicationRegistry.regist(StatisticsEventType.throughputStat, this);

        delayStats = new MapMaker().makeComputingMap(new Function<Long, AvgStat>() {

            public AvgStat apply(Long pipelineId) {
                return new AvgStat();
            }
        });
        throughputStats = new MapMaker().makeComputingMap(new Function<Long, Map<ThroughputType, ThroughputStat>>() {

            public Map<ThroughputType, ThroughputStat> apply(Long pipelineId) {
                return new HashMap<ThroughputType, ThroughputStat>();
            }
        });

        scheduler = new ScheduledThreadPoolExecutor(DEFAULT_POOL, new NamedThreadFactory("Otter-Statistics-Server"),
                                                    new ThreadPoolExecutor.CallerRunsPolicy());
        if (statUnit > 0) {
            scheduler.scheduleAtFixedRate(new Runnable() {

                public void run() {
                    try {
                        flushDelayStat();
                    } catch (Exception e) {
                        logger.error("flush delay stat failed!", e);
                    }
                }
            }, statUnit, statUnit, TimeUnit.MILLISECONDS);

            scheduler.scheduleAtFixedRate(new Runnable() {

                public void run() {
                    try {
                        flushThroughputStat();
                    } catch (Exception e) {
                        logger.error("flush Throughput stat failed!", e);
                    }
                }
            }, statUnit, statUnit, TimeUnit.MILLISECONDS);
        }
    }

    public void onDelayCount(DelayCountEvent event) {
        Assert.notNull(event);
        Assert.notNull(event.getCount());

        // 更新delay queue的计数器
        DelayCount count = event.getCount();
        // 构造一次delay stat快照
        DelayStat stat = new DelayStat();
        stat.setPipelineId(count.getPipelineId());
        stat.setDelayNumber(0L); // 不再记录堆积量
        stat.setDelayTime(count.getTime() >= 0 ? count.getTime() : 0); // 只记录延迟时间,负数直接归为0

        if (statUnit <= 0) {
            delayStatService.createDelayStat(stat);
        } else {
            synchronized (delayStats) {
                delayStats.get(count.getPipelineId()).merge(stat);
            }
        }
    }

    public void onThroughputStat(ThroughputStatEvent event) {
        Assert.notNull(event);
        Assert.notNull(event.getStats());
        if (statUnit <= 0) {
            for (ThroughputStat stat : event.getStats()) {
                throughputStatService.createOrUpdateThroughput(stat);
            }
        } else {
            synchronized (throughputStats) {
                for (ThroughputStat stat : event.getStats()) {
                    Map<ThroughputType, ThroughputStat> data = throughputStats.get(stat.getPipelineId());
                    ThroughputStat old = data.get(stat.getType());
                    if (old != null) {
                        //执行合并
                        old.setNumber(stat.getNumber() + old.getNumber());
                        old.setSize(stat.getSize() + old.getSize());
                        if (stat.getEndTime().after(old.getEndTime())) {
                            old.setEndTime(stat.getEndTime());
                        }

                        if (stat.getStartTime().before(old.getStartTime())) {
                            old.setStartTime(stat.getStartTime());
                        }
                    } else {
                        data.put(stat.getType(), stat);
                    }
                }
            }
        }
    }

    public void onTableStat(TableStatEvent event) {
        Assert.notNull(event);
        Assert.notNull(event.getStats());
        for (TableStat stat : event.getStats()) {
            tableStatService.updateTableStat(stat);
        }
    }

    private void flushDelayStat() {
        synchronized (delayStats) {
            // 需要做同步,避免delay数据丢失
            for (Map.Entry<Long, AvgStat> stat : delayStats.entrySet()) {
                if (stat.getValue().count.get() > 0) {
                    DelayStat delay = new DelayStat();
                    delay.setPipelineId(stat.getKey());
                    delay.setDelayTime(stat.getValue().getAvg());
                    delay.setDelayNumber(0L);
                    delayStatService.createDelayStat(delay);
                }
            }
            delayStats.clear();
        }
    }

    private void flushThroughputStat() {
        synchronized (throughputStats) {
            Collection<Map<ThroughputType, ThroughputStat>> stats = throughputStats.values();
            for (Map<ThroughputType, ThroughputStat> stat : stats) {
                for (ThroughputStat data : stat.values()) {
                    throughputStatService.createOrUpdateThroughput(data);
                }
            }
            throughputStats.clear();
        }
    }

    public static class AvgStat {

        private AtomicLong number = new AtomicLong(0L);
        private AtomicLong count  = new AtomicLong(0L);

        public void merge(DelayStat stat) {
            count.incrementAndGet();
            number.addAndGet(stat.getDelayTime());
        }

        public Long getAvg() {
            if (count.get() > 0) {
                return number.get() / count.get();
            } else {
                return 0L;
            }
        }
    }

    // ===================== setter / getter =====================

    public void setDelayStatService(DelayStatService delayStatService) {
        this.delayStatService = delayStatService;
    }

    public void setTableStatService(TableStatService tableStatService) {
        this.tableStatService = tableStatService;
    }

    public void setThroughputStatService(ThroughputStatService throughputStatService) {
        this.throughputStatService = throughputStatService;
    }

}
TOP

Related Classes of com.alibaba.otter.manager.biz.remote.impl.StatsRemoteServiceImpl$AvgStat

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.