0

我有一个 Spring Boot 应用程序,由于奇怪的限制,它需要每三个小时运行一次,并且不能与 Quartz 一起使用,所以我从 OS cron 每三个小时运行一次它,它在完成后退出。然而,在添加 micrometer-registry-datadog(和 spring-legacy)之后,它永远不会退出,它只是每 20 秒或默认周期发送一次指标,即使在调用 registry.close() 之后也是如此。

我是注定要像荷兰人一样永远在加工的海洋中航行,还是我犯了明显的错误?

代码:它到达 SpringApplication.exit(ctx),但实际上并没有干净地退出。(服务是 TimedExecutorService。)

        public void close() throws InterruptedException {
            service.shutdown();
            service.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
            meterRegistry.close();
            SpringApplication.exit(ctx);
    }
4

1 回答 1

0

这听起来像一个错误。Datadog 导出器可能在非守护线程中运行。JVM 将非守护线程视为应用程序关键工作。

所以本质上JVM认为它不应该在非守护线程完成之前关闭。在 Datadog 导出器线程的情况下,这可能不会发生。

要验证是否存在非守护线程,请使用jstack生成线程转储。(命令jstack <pid>:)或转储close方法中的所有线程:

ThreadMXBean threadMxBean = ManagementFactory.getThreadMXBean();
for (ThreadInfo ti : threadMxBean.dumpAllThreads(true, true)) {
  System.out.print(ti.toString());
}

下面是一个示例线程转储输出。注意第一行的“守护进程”这个词:

"pool-1-thread-1" #13 prio=5 os_prio=31 tid=0x00007fe885aa5000 nid=0xa907 waiting on condition [0x000070000d67b000]
   java.lang.Thread.State: WAITING (parking)
    at sun.misc.Unsafe.park(Native Method)
    - parking to wait for  <0x00000006c07e9720> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
    at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
    at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1081)
    at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:809)
    at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1074)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)
于 2018-05-03T12:59:44.133 回答