Package net.csdn.modules.controller

Source Code of net.csdn.modules.controller.API

package net.csdn.modules.controller;

import com.google.inject.Inject;
import net.csdn.annotation.FDesc;
import net.csdn.annotation.MDesc;
import net.csdn.annotation.Param;
import net.csdn.annotation.rest.At;
import net.csdn.annotation.rest.BasicInfo;
import net.csdn.common.collect.Tuple3;
import net.csdn.common.logging.CSLogger;
import net.csdn.common.logging.Loggers;
import net.csdn.common.settings.Settings;
import org.joda.time.DateTime;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;

/**
* 4/9/14 WilliamZhu(allwefantasy@gmail.com)
*/

public class API {

    class AvgTime {
        AtomicLong timeStart;
        AtomicLong nowTimeRange;
        AtomicLong lastTimeRange;
        AtomicLong count;

        AvgTime(AtomicLong timeStart, AtomicLong nowTimeRange, AtomicLong lastTimeRange, AtomicLong count) {
            this.timeStart = timeStart;
            this.nowTimeRange = nowTimeRange;
            this.lastTimeRange = lastTimeRange;
            this.count = count;
        }
    }

    private Settings settings;
    private CSLogger logger = Loggers.getLogger(API.class);
    /*
      在特定internal 时间内的QPS
     */
    private ConcurrentHashMap<Method, Tuple3<AtomicLong/*时间戳*/, AtomicLong/*当前interval时间内正在累积的访问数*/, AtomicLong/*上一个interval计算出的结果QPS*/>> APIQPS = new ConcurrentHashMap<Method, Tuple3<AtomicLong, AtomicLong, AtomicLong>>();
    private ConcurrentHashMap<Method, AvgTime> APIAVGTIME = new ConcurrentHashMap<Method, AvgTime>();
    /*
      每个API 从系统启动开始,各个http状态码数目
     */
    private ConcurrentHashMap<Method, ConcurrentHashMap<Integer, AtomicLong>> APISTATUS = new ConcurrentHashMap<Method, ConcurrentHashMap<Integer, AtomicLong>>();


    private Long SystemStartTime = 0l;
    private boolean forceAPICheck = false;


    private int internal = 1000;
    private int averageTimeInternal = 1000;

    @Inject
    public API(Settings settings) {
        this.settings = settings;
        this.internal = settings.getAsInt("application.api.qps.internal", 1000);
        this.averageTimeInternal = settings.getAsInt("application.api.qps.average-time-internal", 1000);
        this.forceAPICheck = settings.getAsBoolean("application.api.strict.check", false);
        this.SystemStartTime = System.currentTimeMillis();
    }

    /*
     controller初始化时需要调用该方法
     */
    public void addPath(Method api) {
        APIQPS.putIfAbsent(api, new Tuple3<AtomicLong, AtomicLong, AtomicLong>(new AtomicLong(SystemStartTime), new AtomicLong(), new AtomicLong()));
        APIAVGTIME.putIfAbsent(api, new AvgTime(new AtomicLong(SystemStartTime), new AtomicLong(), new AtomicLong(), new AtomicLong()));
        APISTATUS.putIfAbsent(api, new ConcurrentHashMap<Integer, AtomicLong>());
    }

    /*
      校验API是否填写各种说明
     */
    public boolean validateAPI() {
        if (forceAPICheck) {
            return true;
        }
        return true;
    }


    /*
     收集每个API的详细信息
     */
    public Map<Method, APIDesc> collectAPIInfoes() {
        Map<Method, APIDesc> APIDescs = new HashMap<Method, APIDesc>();
        for (Method method : APIQPS.keySet()) {
            At path = method.getAnnotation(At.class);
            MDesc mDesc = method.getAnnotation(MDesc.class);
            BasicInfo basicInfo = method.getAnnotation(BasicInfo.class);

            APIDesc apiDesc = new APIDesc();
            apiDesc.path = path.path()[0];
            apiDesc.desc = mDesc != null ? mDesc.value() : "";
            apiDesc.qps = APIQPS.get(method).v3().get();
            apiDesc.avgTime = APIAVGTIME.get(method).lastTimeRange.get();
            apiDesc.paramDesces = createParamDescs(method);
            List<ResponseStatus> responseStatuses = new ArrayList<ResponseStatus>();
            for (Map.Entry<Integer, AtomicLong> item : APISTATUS.get(method).entrySet()) {
                ResponseStatus responseStatus = new ResponseStatus();
                responseStatus.status = item.getKey();
                responseStatus.count = item.getValue().get();
                responseStatuses.add(responseStatus);
            }
            apiDesc.responseStatuses = responseStatuses;
            APIDescs.put(method, apiDesc);
        }
        return APIDescs;
    }

    private List<ParamDesc> createParamDescs(Method method) {
        List<ParamDesc> paramDescs = new ArrayList<ParamDesc>();
        Annotation[][] paramAnnoes = method.getParameterAnnotations();
        Class[] types = method.getParameterTypes();
        for (int i = 0; i < paramAnnoes.length; i++) {
            Annotation[] paramAnno = paramAnnoes[i];
            if (paramAnno.length == 0) continue;
            ParamDesc paramDesc = new ParamDesc();
            for (Annotation item : paramAnno) {
                if (item instanceof FDesc) {
                    paramDesc.desc = ((FDesc) item).value();
                }
                if (item instanceof Param) {
                    paramDesc.name = ((Param) item).value();
                }
            }
            paramDesc.ptype = types[i].getName();
            paramDescs.add(paramDesc);
        }
        return paramDescs;
    }

    public boolean enable() {
        return (settings.getAsBoolean("application.api.qps.enable", false));
    }

    /*
      QPS 统计
     */
    public synchronized void qpsIncrement(Method api) {
        if (!enable() || api == null) return;
        long now = System.currentTimeMillis();
        Tuple3<AtomicLong, AtomicLong, AtomicLong> info = APIQPS.get(api);
        if (now - info.v1().get() > internal) {
            info.v3().set(info.v2().get());
            info.v2().set(0);
            info.v1().set(now);
        } else {
            info.v2().incrementAndGet();
        }

    }

    public synchronized void averageTimeIncrement(Method api, long time) {
        if (!enable() || api == null) return;
        long now = System.currentTimeMillis();
        AvgTime info = APIAVGTIME.get(api);
        info.count.incrementAndGet();
        if (now - info.timeStart.get() > averageTimeInternal) {
            if (info.count.get() == 0) {
                info.lastTimeRange.set(0);
            } else {
                info.lastTimeRange.set(info.nowTimeRange.get() / info.count.get());
            }
            info.nowTimeRange.set(0);
            info.timeStart.set(now);
        } else {
            info.nowTimeRange.addAndGet(time);
        }

    }

    /*
      状态码统计
     */
    public synchronized void statusIncrement(Method api, int status) {
        if (!enable() || api == null) return;
        ConcurrentHashMap<Integer, AtomicLong> chm = APISTATUS.get(api);
        if (!chm.containsKey(status)) {
            chm.put(status, new AtomicLong());
        }
        chm.get(status).incrementAndGet();
    }

    public String systemStartTime() {
        return new DateTime(SystemStartTime).toString("yyyy-MM-dd HH-mm-ss S");
    }

}
TOP

Related Classes of net.csdn.modules.controller.API

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.