开发者社区> 问答> 正文

如何在SpringBoot中分析复杂的http请求处理?

我有一个复杂的@RestController方法,如下所示:

@PostMapping("{id}")
@PreAuthorize("hasRole('ADMIN')")
@Transactional
public Response handleRequest(@PathVariable("id") long id, @RequestBody @Valid Request request) {
    return service.handleRequest(id, request);
}

我们的请求处理非常慢,因此我们希望检查在特定请求处理任务上花费了多少时间。不幸的是,很多事情都是在我的方法之外完成的,比如:

反序列化请求 验证 权限检查 开始和结束事务 序列化响应 有没有办法简单地测量所有这些部件?也许一组记录器接收跟踪消息,这样我就可以在每一步的末尾提取时间戳了?

我现在看到的唯一方法是更改该方法以接受HttpServletRequest和HttpServletResponse,并在方法主体中执行这些部分。但是那样的话,我就会失去很多Spring Boot的好处。

展开
收起
几许相思几点泪 2019-11-28 16:31:43 930 0
1 条回答
写回答
取消 提交回答
  • 没有必要更改该方法以期待HttpServletRequest。你可以用AspectJ

    使用它,您可以收集在每个方法上花费的时间,并从中分析数据。

    创建一个方法--时间标注

    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.METHOD)
    public @interface MethodTiming {
    }
    
    

    在您的请求中,创建一个将保留所有方法及其所用时间的映射:

    public class Request {
    private Map<String, Long> methodTimings = new TreeMap<String, Long>();
    
    public void addMethodTiming(String classAndMethodName, long executionTimeMillis) {
          Long value = methodTimings.get(classAndMethodName);
          if (value != null) {
              executionTimeMillis += value;
          }
    
          methodTimings.put(classAndMethodName, executionTimeMillis);
      }
    }
    
    

    创建处理它的方面类:

    @Aspect
    @Component
    public class MethodTimingAspect {
    private static final String DOT = ".";
    
    @Around("@annotation(MethodTiming)")
    public Object timeAround(ProceedingJoinPoint joinPoint) throws Throwable  {
        Object result = null;
    
        StopWatch watch = new StopWatch();
        try {
            watch.start();
            result = joinPoint.proceed();
        } finally {
            watch.stop();
            long executionTime = watch.getLastTaskTimeMillis();
    
            String className = joinPoint.getTarget().getClass().getSimpleName();
            String methodName = joinPoint.getSignature().getName();
            String classAndMethodName = className + DOT + methodName;
    
            Object[] methodArgs = joinPoint.getArgs();
            if (methodArgs != null) {
                for (Object arg : methodArgs) {
                    if (arg instanceof Request) {
                        // inject time back into Request
                        Request request = (Request) arg;
                        request.addMethodTiming(classAndMethodName, executionTime);
    
                        break;
                    }
                }
            }
    
        }
        return result;
    }
    
    

    最后,只需在您希望度量的方法上添加@MethodTiming:

    @MethodTiming
    public Request handleRequest(Request request) {
    // handle the Request
    return request
    }
    
    

    您的请求对象在处理之后将有如下所示

    "methodTimings": {
        "RequestService.handleRequest": 2610,
        "AnotherRequestService.anotherMethod": 1351
    }
    
    2019-11-28 16:33:45
    赞同 展开评论 打赏
问答排行榜
最热
最新

相关电子书

更多
阿里巴巴HTTP 2.0实践及无线通信协议的演进之路 立即下载
CDN助力企业网站进入HTTPS时代 立即下载
低代码开发师(初级)实战教程 立即下载