如何通过多个线程追踪JFR事件

时间:2019-05-20 13:07:32

标签: java-11 jmc jfr java-mission-control

我正在努力通过自定义JFR事件为异步servlet请求处理建模。 我面临的挑战是,在异步处理中,一个请求可能会#dispatch()多次。这意味着整个请求处理链可以多次执行,有时在不同的线程中执行。如何使用自定义JFR事件对此建模?

对我有帮助的是“父”事件(可能在不同的线程中)的概念,或者事件的中止和恢复。

修改

稍微说明一下这个问题。异步请求可能需要100秒的挂钟时间来处理。但是,使用Servlet#service()方法,实际的处理可能仅在用户时间4秒钟内发生:

  • 线程A中的第二个0-1,Servlet#service()方法返回,AsyncContext开始
  • 线程B中的第二个10-11,Servlet#service()方法返回,AsyncContext开始
  • 线程A中第二秒80-81,Servlet#service()方法返回,AsyncContext开始
  • 线程C中的秒99-100,Servlet#service()方法返回

我只想在这三个线程的四个持续时间内生成事件,然后将它们与单个请求相关联。

2 个答案:

答案 0 :(得分:3)

您可以将线程字段添加到事件中

public class MyEvent extends Event [
  @Label("Start Thread")
  @TranistionFrom
  private final Thread startThread;
  MyEvent(Thread thread) {
    this.startThread = thread;
  }
]

提交事件时,将存储结束线程。

如果要在多个线程上跟踪事件,则需要为每个线程创建一个事件并有一个ID,以便您了解流程。

class MyEvent extends Event {

  @Label("Transition id");
  long id;
}

如果您愿意,可以创建一个关系ID来描述该关系,并且JMC应该能够提示(在上下文菜单等中)事件之间的关系。

@Label("Transition Id")
@Relational
@Target({ ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
@interface TransitionId {
}

如果不想重复自己,可以在基类的方法中编写以上功能,您可以为事件访问的每个新线程调用该方法。

 abstract AbstractTransition extends Event {

   @TransitionId
   @Label("Transition Id")
   private long id;
   public void setTransitionId(long id) {
     this.id = id;
   }
 }

没有其他方法可以执行此操作。

JVM无法知道事件对象位于哪个线程中,或者应该记录哪些线程。用户需要为每个应该触摸的线程(以及一些上下文)提供至少一个方法调用。

答案 1 :(得分:1)

问题类似于如何在分布式跟踪器中将跨度和范围的JFR事件绑定在一起。

本文可能会帮助您: http://hirt.se/blog/?p=1081