如何在多个线程上追踪 JFR 事件

Phi*_*all 4 jmc java-mission-control jfr java-11

我正在努力使用自定义 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()方法返回

我只对在这三个线程中为这四个持续时间生成事件感兴趣,然后将它们与单个请求相关联。

Kir*_*lin 5

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

public class MyEvent extends Event [
  @Label("Start Thread")
  @TransitionFrom
  private final Thread startThread;
  MyEvent(Thread thread) {
    this.startThread = thread;
  }
]
Run Code Online (Sandbox Code Playgroud)

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

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

class MyEvent extends Event {

  @Label("Transition id");
  long id;
}
Run Code Online (Sandbox Code Playgroud)

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

@Label("Transition Id")
@Relational
@Target({ ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
@interface TransitionId {
}
Run Code Online (Sandbox Code Playgroud)

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

 abstract AbstractTransition extends Event {

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

没有其他方法可以做到这一点。

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