如何高效地统计每个接口的调用次数?

写了个拦截器,每调用一个接口,开启一个新的线程计数+1。因为计数与系统逻辑是分开的,所以放在另外一个线程里。

但是这样是否会带来负载过高?有没有什么好的解决办法?按照key-value周期性的存储吗?

现在代码如下:

public class ModuleStatisticsInterceptor implements Interceptor {

/**
* 统计接口调用次数
*/
@Override
public void intercept(Invocation inv) {
    String controllerPath = inv.getControllerKey();
    APICallCount(controllerPath.substring(1, controllerPath.length()), inv.getMethodName());
    inv.invoke();
}
/**
* 统计接口调用次数(另外的线程中执行)
* @param className controller类名
* @param methodName controller中的方法名
*/
public static void APICallCount(String className, String methodName) {
    new Thread(new Runnable() {
            public void run() {
                try {
                    Record record = Db.findFirst("SELECT controllerName FROM module_statistics WHERE controllerName = ? AND methodName = ?", className, methodName);
                    if(record == null) {
                    Db.update("INSERT INTO module_statistics(controllerName, methodName, count, state) values(?,?, 0, 1)", className, methodName);
                }
                Db.update("UPDATE module_statistics SET count = count + 1 WHERE controllerName = ? AND methodName = ? LIMIT 1", className, methodName);  
                } catch (Exception ex) {
                    LogKit.error("统计出错:" + className + "/" + methodName);
                }
            }
        }).start();
}

}


评论区

JFinal

2018-05-30 17:42

计数用 java 中的 AtomicLong 即可,即可以保障原子性,又可以保障性能

然后用 jfinal 提供的 Cron4jPlugin 插件定时将这个 AtomicLong 值写入数据库,并且清零

AtomicLong 放在一个全局拦截器中即可

KevinQWW

2018-05-30 18:08

@JFinal 谢波总,涨知识了。一会儿实验一下,看看redis/AtomicLong/LongAdder的速度对比。

潇洒太爷

2018-05-30 20:43

可以看下jboot怎么使用metric

热门反馈

扫码入社