当前位置: 首页 > 知识库问答 >
问题:

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

华升
2023-03-14

我有复杂的@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的好处。

共有3个答案

邓元白
2023-03-14

无需更改期望 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 类:

@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
}
钮瀚
2023-03-14

您真正需要的是Java线程分析器,它将告诉您到底出了什么问题,为此您可以使用任何APM工具,我最喜欢的是GLOWROOT,我在类似场景中使用它来测量API的性能并识别慢速跟踪,这将清楚地告诉您哪种方法需要时间,您可以看到从方法调用到所有方法的整个跟踪在内部调用,甚至可以识别慢查询(如果有)。希望这有帮助

网站: https://glowroot.org/

示例跟踪:

https://demo.glowroot.org/transaction/thread-profile?transaction-type=Web

公沈义
2023-03-14

您还可以检查 tuto 以添加执行器的自定义指标,但这似乎有点复杂(但您必须编写自己的指标 bean 并将其注入到您的代码中,覆盖 objectMapper 进行映射等......

或者可以激活Jackson,Spring-Security,javax.validation上的日志记录信息,以检查每个操作的日志中的时间,但不是很精确

 类似资料:
  • 问题内容: 看来我应该这样做: 通过将其设置为来配置dispatcherServlet 但是,考虑到我没有XML配置,或者代码中没有任何各种初始化程序类(此答案提到),该怎么做? 在一个类中,我有一个像这样的方法,当前不会被调用。 Spring Boot 1.2.7.RELEASE; 一个简单的设置与Spring REST指南并没有太大区别 。 问题答案: 选项1:Spring Boot属性(仅适

  • 我是web服务新手,正在阅读Martin Kalin的《Java Webservices》一书。我已经了解了它最初的基本概念,有一个问题: 假设将HTTP请求(包含SOAP消息信封)发送到JavaWeb服务()。该请求是否由Servlet内部处理,Servlet提取SOAP消息并将其转换为相应Java域对象,然后调用服务实现bean? 无论Metro和Axis等现成框架如何,这个问题都是通用的。只

  • 首先,我阅读了“如何使用Spring MVC处理HTTP选项?”但答案似乎并不直接适用于Spring Boot。 看起来我应该这么做: 通过将dispatcherServlet的设置为 但是,考虑到我的代码中没有XML配置,也没有任何种类的初始化器类(在这个答案中提到),如何做到这一点呢? 在一个类中,我有一个这样的方法,它目前没有被调用。 Spring靴1.2.7。释放一个简单的设置与Sprin

  • 我正在运行,刚刚检查了服务器日志,并出现了几个类似的错误。我不明白是什么导致了它,因为错误每天都在12/24小时后出现。

  • 我正在使用Amazon SNS在我的HTTP/HTTPSendpoint上接收推送消息。endpoint应用程序是用Django编写的。要在endpoint(web app)上接收通知,HTTP/HTTPSendpoint需要订阅一个主题。 我的问题是当Amzaon SNS发送订阅确认时,它如何在POST请求中发送CSRF令牌,以便我处理请求并检索所需信息? 文档:http://docs.aws.

  • 问题内容: 我在我的应用程序中使用JSF框架。我需要在“阶段侦听器”类中的渲染响应阶段之前运行特定的脚本。 运行此脚本的条件是,如果触发的请求是Ajax请求,则需要运行该脚本;如果触发的请求是Http请求,则不应运行该脚本。 谁能帮我区分收到的请求吗? 问题答案: Ajax请求通常具有一个请求标头。在JSF中,您可以通过获得请求标头。

  • 当我试图从spring boot应用程序访问OAuth HTTPSendpoint时,我得到了以下错误,但HTTPendpoint工作得非常好 错误: 安全java配置 POM文件

  • 通常用于HTTP/HTTPS请求失败/成功等处理. 进程: 主进程​ IncomingMessage是由 EventEmitter响应可读流接口 实例事件 事件: 'data' 用途:响应或回调传送到应用的数据 chunk Buffer - 响应正文的数据块. 事件: 'end' 触发:响应正文已结束时 事件: 'aborted' 触发:正在进行的HTTP事务期间请求已取消时 事件: 'error