欢迎访问昆山宝鼎软件有限公司网站! 设为首页 | 网站地图 | XML | RSS订阅 | 宝鼎邮箱 | 后台管理


新闻资讯

MENU

软件开发知识
原文出处: 琴水玉

引语

作为工程师,不能仅仅满意于实现了现有的成果逻辑,还必需深入认识系统。一次请求,流经了哪些要领,执行了几多次DB操纵,会见了几多次文件操纵,挪用几多次API操纵,总共有几多次IO操纵,几多CPU操纵,各耗时几多 ? 开拓者该当知道这些运行时数据,才气对系统的运行有更深入的领略,更好滴晋升系统的机能和不变性。

完成一次订单导出任务,实际上是一个较量巨大的进程:需要会见ES 来查询订单,挪用批量API接口 及会见 Hbase 获取订单详情数据,名目化报表字段数据,写入和上传报表文件,更新数据库,上报日志数据等;在大流量导出的景象下,回收批量并发计策,多线程来获取订单详情数据,劳务派遣管理系统,整个请求的执行流程会越发巨大。

本文主要先容利用AOP拦截器来获取一次请求流经要领的挪用次数和挪用耗时。

总体思路

利用AOP思想来办理。增加一个注解,然后增加一个AOP methodAspect ,记录要领的挪用次数及耗时。

methodAspect 内部含有两个变量 methodCount, methodCost ,都回收了 ConcurrentHashMap 。这是因为要领执行时,大概是多线程写入这两个变量。

利用:

(1) 将需要记录次数和耗时的要领加上 MethodMeasureAnnotation 即可;

(2) 将 MethodMeasureAspect 作为组件注入到 ServiceAspect 中,并在 ServiceAspect 中打印 MethodMeasureAspect 的内容。

存眷哪些要领

凡是重点存眷一个任务流程中的如下要领:

  • IO阻塞操纵:文件操纵, DB操纵,API操纵, ES会见,Hbase会见;
  • 同步操纵:lock, synchronized, 同步东西所施加的代码块等;
  • CPU耗时:大数据量的format, sort 等。
  • 一般会合在如下包:

  • service, core , report, sort 等。按照详细项目而定。
  • 源代码

    package zzz.study.aop;
    
    import zzz.study.util.MapUtil;
    
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.Signature;
    import org.aspectj.lang.annotation.Around;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.reflect.MethodSignature;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.stereotype.Component;
    
    import java.lang.reflect.Method;
    import java.util.ArrayList;
    import java.util.IntSummaryStatistics;
    import java.util.List;
    import java.util.Map;
    import java.util.concurrent.ConcurrentHashMap;
    import java.util.stream.Collectors;
    
    /**
     * 记录一次请求中,流经的所有要领的挪用耗时及次数
     *
     */
    @Component
    @Aspect
    public class MethodMeasureAspect {
    
      private static final Logger logger = LoggerFactory.getLogger(MethodMeasureAspect.class);
    
      private Map<String, Integer> methodCount = new ConcurrentHashMap();
    
      private Map<String, List<Integer>> methodCost = new ConcurrentHashMap();
    
      @SuppressWarnings(value = "unchecked")
      @Around("@annotation(zzz.study.aop.MethodMeasureAnnotation)")
      public Object process(ProceedingJoinPoint joinPoint) {
        Object obj = null;
        String className = joinPoint.getTarget().getClass().getSimpleName();
        String methodName = className + "_" + getMethodName(joinPoint);
        long startTime = System.currentTimeMillis();
        try {
          obj = joinPoint.proceed();
        } catch (Throwable t) {
          logger.error(t.getMessage(), t);
        } finally {
          long costTime = System.currentTimeMillis() - startTime;
          logger.info("method={}, cost_time={}", methodName, costTime);
          methodCount.put(methodName, methodCount.getOrDefault(methodName, 0) + 1);
          List<Integer> costList = methodCost.getOrDefault(methodName, new ArrayList<>());
          costList.add((int)costTime);
          methodCost.put(methodName, costList);
        }
        return obj;
      }
    
      public String getMethodName(ProceedingJoinPoint joinPoint) {
        Signature signature = joinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method method = methodSignature.getMethod();
        return method.getName();
      }
    
      public String toString() {
    
        StringBuilder sb = new StringBuilder("MethodCount:\n");
        Map<String,Integer> sorted =  MapUtil.sortByValue(methodCount);
        sorted.forEach(
            (method, count) -> {
              sb.append("method=" + method + ", " + "count=" + count+'\n');
            }
        );
        sb.append('\n');
        sb.append("MethodCosts:\n");
        methodCost.forEach(
            (method, costList) -> {
              IntSummaryStatistics stat = costList.stream().collect(Collectors.summarizingInt(x->x));
              String info = String.format("method=%s, sum=%d, avg=%d, max=%d, min=%d, count=%d", method,
                                          (int)stat.getSum(), (int)stat.getAverage(), stat.getMax(), stat.getMin(), (int)stat.getCount());
              sb.append(info+'\n');
            }
        );
    
        sb.append('\n');
        sb.append("DetailOfMethodCosts:\n");
        methodCost.forEach(
            (method, costList) -> {
              String info = String.format("method=%s, cost=%s", method, costList);
              sb.append(info+'\n');
            }
        );
        return sb.toString();
      }
    }