com.alibaba.otter.manager.biz.autokeeper.impl.AutoKeeperCollector.java Source code

Java tutorial

Introduction

Here is the source code for com.alibaba.otter.manager.biz.autokeeper.impl.AutoKeeperCollector.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.autokeeper.impl;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import javax.annotation.Resource;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.InitializingBean;

import com.alibaba.otter.manager.biz.common.exceptions.ManagerException;
import com.alibaba.otter.manager.biz.config.autokeeper.AutoKeeperClusterService;
import com.alibaba.otter.manager.biz.utils.RegexUtils;
import com.alibaba.otter.shared.common.model.autokeeper.AutoKeeperCluster;
import com.alibaba.otter.shared.common.model.autokeeper.AutoKeeperConnectionStat;
import com.alibaba.otter.shared.common.model.autokeeper.AutoKeeperEphemeralStat;
import com.alibaba.otter.shared.common.model.autokeeper.AutoKeeperQuorumType;
import com.alibaba.otter.shared.common.model.autokeeper.AutoKeeperServerStat;
import com.alibaba.otter.shared.common.model.autokeeper.AutoKeeperWatchStat;
import com.alibaba.otter.shared.common.utils.cmd.Exec;
import com.alibaba.otter.shared.common.utils.cmd.Exec.Result;
import com.alibaba.otter.shared.common.utils.thread.NamedThreadFactory;

/**
 * ?
 * 
 * @author jianghang 2012-9-21 ?03:05:28
 * @version 4.1.0
 */
public class AutoKeeperCollector implements InitializingBean {

    @Resource(name = "autoKeeperClusterService")
    private AutoKeeperClusterService autoKeeperClusterService;

    private static final String MODE_FOLLOWER = "Mode: follower";
    private static final String MODE_LEADERER = "Mode: leader";
    private static final String MODE_OBSERVER = "Mode: observer";
    private static final String MODE_STANDALONE = "Mode: standalone";
    private static final String NODE_COUNT = "Node count:";
    private static final String STRING_LATENCY = "Latency min/avg/max:";
    private static final String STRING_SENT = "Sent:";
    private static final String STRING_RECEIVED = "Received:";
    private static final String STRING_OUTSTANDING = "Outstanding:";
    private static final String COMMA = ",";
    private static final String BRACKETS = ")";
    private static final String COLON = ":";
    private static final String WRAP = "\n";
    private static final String CMD_STAT = "echo stat | nc %s %s";
    private static final String CMD_CONS = "echo cons | nc %s %s";
    private static final String CMD_DUMP = "echo dump | nc %s %s";
    private static final String CMD_WCHC = "echo wchc | nc %s %s";
    private static final long DEFAULT_COLLECT_INTERVAL = 300;
    private long delay = 1;
    private int singleSize = 1;
    private long collectInterval = DEFAULT_COLLECT_INTERVAL;

    private AutoKeeperData autoKeeperData;
    private ScheduledExecutorService collectorExecutor;

    public void collectorConnectionStat(String address) {
        List<String> netAddress = splitAddress(address);
        if (netAddress.isEmpty()) {
            return;
        }
        String ip = netAddress.get(0);
        String port = netAddress.get(1);
        String[] cmd = { "/bin/bash", "-c", String.format(CMD_CONS, ip, port) };
        String cmdresult = collector(cmd);
        String[] result = cmdresult.split(WRAP);
        List<AutoKeeperConnectionStat> summary = new ArrayList<AutoKeeperConnectionStat>();

        for (String line : result) {

            if (StringUtils.isBlank(line)) {
                continue;
            }

            String[] lineArray = line.split(":");
            if (2 != lineArray.length) {
                continue;
            }

            AutoKeeperConnectionStat autoKeeperConnectionStat = new AutoKeeperConnectionStat();
            autoKeeperConnectionStat.setOriginalContent(line);
            String clientIp = StringUtils.trimToEmpty(line.split(":")[0].replace("/", ""));
            String sessionId = StringUtils.trimToEmpty(RegexUtils.findFirst(line.split(":")[1], "sid=(?s).*?[,)]"))
                    .replace("sid=", StringUtils.EMPTY).replace(COMMA, StringUtils.EMPTY)
                    .replace(BRACKETS, StringUtils.EMPTY);
            String queued = StringUtils.trimToEmpty(RegexUtils.findFirst(line.split(":")[1], "queued=(?s).*?[,)]"))
                    .replace("queued=", StringUtils.EMPTY).replace(COMMA, StringUtils.EMPTY)
                    .replace(BRACKETS, StringUtils.EMPTY);
            String receive = StringUtils.trimToEmpty(RegexUtils.findFirst(line.split(":")[1], "recved=(?s).*?[,)]"))
                    .replace("recved=", StringUtils.EMPTY).replace(COMMA, StringUtils.EMPTY)
                    .replace(BRACKETS, StringUtils.EMPTY);
            String sent = StringUtils.trimToEmpty(RegexUtils.findFirst(line.split(":")[1], "sent=(?s).*?[,)]"))
                    .replace("sent=", StringUtils.EMPTY).replace(COMMA, StringUtils.EMPTY)
                    .replace(BRACKETS, StringUtils.EMPTY);
            String minlat = StringUtils.trimToEmpty(RegexUtils.findFirst(line.split(":")[1], "minlat=(?s).*?[,)]"))
                    .replace("minlat=", StringUtils.EMPTY).replace(COMMA, StringUtils.EMPTY)
                    .replace(BRACKETS, StringUtils.EMPTY);
            String avglat = StringUtils.trimToEmpty(RegexUtils.findFirst(line.split(":")[1], "avglat=(?s).*?[,)]"))
                    .replace("avglat=", StringUtils.EMPTY).replace(COMMA, StringUtils.EMPTY)
                    .replace(BRACKETS, StringUtils.EMPTY);
            String maxlat = StringUtils.trimToEmpty(RegexUtils.findFirst(line.split(":")[1], "maxlat=(?s).*?[,)]"))
                    .replace("maxlat=", StringUtils.EMPTY).replace(COMMA, StringUtils.EMPTY)
                    .replace(BRACKETS, StringUtils.EMPTY);
            autoKeeperConnectionStat.setServerAddress(ip);
            autoKeeperConnectionStat.setClientAddress(clientIp);
            autoKeeperConnectionStat.setSessionId(sessionId);
            if (StringUtils.isNotEmpty(queued)) {
                autoKeeperConnectionStat.setQueued(Long.parseLong(queued));
            }
            if (StringUtils.isNotEmpty(receive)) {
                autoKeeperConnectionStat.setRecved(Long.parseLong(receive));
            }
            if (StringUtils.isNotEmpty(sent)) {
                autoKeeperConnectionStat.setSent(Long.parseLong(sent));
            }
            if (StringUtils.isNotEmpty(minlat)) {
                autoKeeperConnectionStat.setMinLatency(Long.parseLong(minlat));
            }
            if (StringUtils.isNotEmpty(avglat)) {
                autoKeeperConnectionStat.setAvgLatency(Long.parseLong(avglat));
            }
            if (StringUtils.isNotEmpty(maxlat)) {
                autoKeeperConnectionStat.setMaxLatency(Long.parseLong(maxlat));
            }

            summary.add(autoKeeperConnectionStat);
        }
        autoKeeperData.joinConnection(address, summary);
    }

    public void collectorServerStat(String address) {
        List<String> netAddress = splitAddress(address);
        if (netAddress.isEmpty()) {
            return;
        }
        String ip = netAddress.get(0);
        String port = netAddress.get(1);
        String[] cmd = { "/bin/bash", "-c", String.format(CMD_STAT, ip, port) };
        String cmdresult = collector(cmd);
        String[] result = cmdresult.split(WRAP);
        AutoKeeperServerStat summary = new AutoKeeperServerStat();
        summary.setOriginalContent(cmdresult);
        for (String line : result) {

            if (line.contains(MODE_FOLLOWER)) {
                summary.setQuorumType(AutoKeeperQuorumType.FOLLOWER);
            } else if (line.contains(MODE_LEADERER)) {
                summary.setQuorumType(AutoKeeperQuorumType.LEADER);
            } else if (line.contains(MODE_STANDALONE)) {
                summary.setQuorumType(AutoKeeperQuorumType.STANDALONE);
            } else if (line.contains(MODE_OBSERVER)) {
                summary.setQuorumType(AutoKeeperQuorumType.OBSERVER);
            } else if (line.contains(STRING_LATENCY)) {
                List<String> latency = Arrays.asList(
                        StringUtils.trimToEmpty(line.replace(STRING_LATENCY, StringUtils.EMPTY)).split("/"));
                summary.setMinLatency(Long.parseLong(latency.get(0)));
                summary.setAvgLatency(Long.parseLong(latency.get(1)));
                summary.setMaxLatency(Long.parseLong(latency.get(2)));
            } else if (line.contains(STRING_OUTSTANDING)) {
                summary.setQueued(Long
                        .parseLong(StringUtils.trimToEmpty(line.replace(STRING_OUTSTANDING, StringUtils.EMPTY))));
            } else if (line.contains(NODE_COUNT)) {
                summary.setNodeCount(
                        Long.parseLong(StringUtils.trimToEmpty(line.replace(NODE_COUNT, StringUtils.EMPTY))));
            } else if (line.contains(STRING_SENT)) {
                summary.setSent(
                        Long.parseLong(StringUtils.trimToEmpty(line.replace(STRING_SENT, StringUtils.EMPTY))));
            } else if (line.contains(STRING_RECEIVED)) {
                summary.setRecved(
                        Long.parseLong(StringUtils.trimToEmpty(line.replace(STRING_RECEIVED, StringUtils.EMPTY))));
            }
        }

        autoKeeperData.joinServer(address, summary);
    }

    public void collectorEphemeralStat(String address) {
        List<String> netAddress = splitAddress(address);
        if (netAddress.isEmpty()) {
            return;
        }
        String ip = netAddress.get(0);
        String port = netAddress.get(1);
        String[] cmd = { "/bin/bash", "-c", String.format(CMD_DUMP, ip, port) };
        String cmdresult = collector(cmd);

        Map<String, List<String>> pathMap = groupSessionPath(cmdresult);

        List<AutoKeeperEphemeralStat> autoKeeperEphemeralStats = new ArrayList<AutoKeeperEphemeralStat>();
        for (Map.Entry<String, List<String>> entry : pathMap.entrySet()) {
            AutoKeeperEphemeralStat autoKeeperEphemeralStat = new AutoKeeperEphemeralStat();
            autoKeeperEphemeralStat.setSessionId(entry.getKey());
            autoKeeperEphemeralStat.setPaths(entry.getValue());
            autoKeeperEphemeralStats.add(autoKeeperEphemeralStat);
        }

        autoKeeperData.joinEphemeral(address, autoKeeperEphemeralStats);

    }

    public void collectorWatchStat(String address) {
        List<String> netAddress = splitAddress(address);
        if (netAddress.isEmpty()) {
            return;
        }
        String ip = netAddress.get(0);
        String port = netAddress.get(1);
        String[] cmd = { "/bin/bash", "-c", String.format(CMD_WCHC, ip, port) };
        String cmdresult = collector(cmd);

        Map<String, List<String>> pathMap = groupSessionPath(cmdresult);

        List<AutoKeeperWatchStat> autoKeeperWatchStats = new ArrayList<AutoKeeperWatchStat>();
        for (Map.Entry<String, List<String>> entry : pathMap.entrySet()) {
            AutoKeeperWatchStat autoKeeperWatchStat = new AutoKeeperWatchStat();
            autoKeeperWatchStat.setSessionId(entry.getKey());
            autoKeeperWatchStat.setPaths(entry.getValue());
            autoKeeperWatchStats.add(autoKeeperWatchStat);
        }

        autoKeeperData.joinWatch(address, autoKeeperWatchStats);

    }

    public static String collector(String[] command) {
        Result result = null;
        try {
            result = Exec.execute(command);
            if (result.getExitCode() == 0) {
                return result.getStdout();
            } else {
                return result.getStderr();
            }
        } catch (Exception e) {
            throw new ManagerException(e);
        }
    }

    private List<String> splitAddress(String address) {
        List<String> ipPort = Arrays.asList(address.split(":"));
        if (ipPort.size() != 2) {
            return new ArrayList<String>();
        }
        return ipPort;
    }

    /**
     * <pre>
     * key=sessionId
     * value=pathList
     * </pre>
     */
    private Map<String, List<String>> groupSessionPath(String cmdresult) {
        String[] result = cmdresult.split(WRAP);

        Map<String, List<String>> pathMap = new HashMap<String, List<String>>();
        String sessionId = StringUtils.EMPTY;
        for (String line : result) {
            line = StringUtils.trimToEmpty(line);
            if (StringUtils.isBlank(line)) {
                continue;
            }
            if (line.startsWith("0x")) {
                sessionId = line.replace(COLON, StringUtils.EMPTY);
                pathMap.put(sessionId, new ArrayList<String>());
            } else if (line.startsWith("/")) {
                List<String> paths = pathMap.get(sessionId);
                paths.add(line);
            }
        }
        return pathMap;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        collectorExecutor = Executors.newScheduledThreadPool(singleSize,
                new NamedThreadFactory("collector-thread", true));
        startCollect();
    }

    private void startCollect() {

        // ?
        collectorExecutor.scheduleAtFixedRate(new Runnable() {

            @Override
            public void run() {
                List<AutoKeeperCluster> autoKeeperClusters = autoKeeperClusterService.listAutoKeeperClusters();
                if (!autoKeeperClusters.isEmpty()) {
                    autoKeeperData.persist();
                    for (AutoKeeperCluster autoKeeperCluster : autoKeeperClusters) {
                        List<String> servers = autoKeeperCluster.getServerList();
                        for (String address : servers) {
                            collectorServerStat(address);
                            collectorConnectionStat(address);
                            collectorWatchStat(address);
                            collectorEphemeralStat(address);
                        }
                    }
                }
            }
        }, delay, collectInterval, TimeUnit.SECONDS);

    }

    public void setAutoKeeperClusterService(AutoKeeperClusterService autoKeeperClusterService) {
        this.autoKeeperClusterService = autoKeeperClusterService;
    }

    public void setAutoKeeperData(AutoKeeperData autoKeeperData) {
        this.autoKeeperData = autoKeeperData;
    }

    public void setCollectInterval(long collectInterval) {
        this.collectInterval = collectInterval;
    }

}