Java 如何记录WELD SE容器关闭的原因

Java 如何记录WELD SE容器关闭的原因,java,weld-se,Java,Weld Se,编辑:原来我的docker容器正在关闭,因为错误的健康检查失败。这导致kubernetes探测器多次失败,导致吊舱死亡。由于该命令来自JVM外部,因此代码可能无法知道JVM周围的容器何时被终止。把这个问题留着,以防有人找到答案 我有一个JavaSE项目,它读入参数来处理文件。我使用焊接SE进行注射。运行几分钟后,焊接容器停止运行,无需解释。下面是我的代码框架。这是我的主课 @ApplicationScoped public class Main { @Setter //Lombok ann

编辑:原来我的docker容器正在关闭,因为错误的健康检查失败。这导致kubernetes探测器多次失败,导致吊舱死亡。由于该命令来自JVM外部,因此代码可能无法知道JVM周围的容器何时被终止。把这个问题留着,以防有人找到答案

我有一个JavaSE项目,它读入参数来处理文件。我使用焊接SE进行注射。运行几分钟后,焊接容器停止运行,无需解释。下面是我的代码框架。这是我的主课

@ApplicationScoped
public class Main {

  @Setter //Lombok annotation
  private Scheduler scheduler;

  public void schedule(String[] filenames) throws InterruptedException {
    scheduler.schedule(filenames);
  }

  @PreDestroy
  public void cleanUp() {
    log.info("PreDestroy - Main");
    //clean up omitted
  }

  public static void main(String[] args) {
    Weld weld = new Weld();
    Main main = null;
    try (WeldContainer container = weld.initialize()) {
      main = container.select(Main.class).get();
      Scheduler scheduler = CDI.current().select(Scheduler.class).get();
      main.setScheduler(scheduler);
      main.schedule(args);
      log.info("Main - completed processing");
    } catch (Exception e) {
      log.info("Exception occurred: " + e.getMessage(), e);
    } finally {
      log.info("Main Finally - Shutting down Weld");
      CDI.current().destroy(main);
      weld.shutdown();
    }
  }
}
这是我的调度程序类

@Named
public class Scheduler {

  private ThreadPoolExecutor executor;
  private Map<Future<?>, Importer> beanMap = new HashMap<>();
  private static final Duration sleepDuration = Duration.ofSeconds(45);

  @PostConstructor
  public void init() {
    //setup executor
  }

  @PreDestroy
  public void cleanUp() {
    log.info("PreDestroy - Scheduler");
    //clean up omitted
  }

  public void schedule(String[] filenames) throws InterruptedException {
    for(String filename : filenames) {
      Importer caller = CDI.current().select(Importer.class).get();
      caller.setFilename(filename);
      Future<?> future = executor.submit(caller);
      beanMap.put(future, caller);
    }

    while(!isDone()) {
       Thread.sleep(sleepDuration.toMillis());
       log.info("Remaining threads: {}, getRemaining());
       destroyCompleted();
    }
  }

  //Returns true only when all threads are completed
  private boolean isDone() { //code omitted }

  //Returns number of not completed threads
  private int getRemaining() { //code omitted }

  //Clean up any completed Importers
  private boolean destroyCompleted() { //code omitted }
}

我正在调试级别记录“org.jboss”。我可以看到容器在处理文件的中途被关闭,但我不明白为什么会发生这种情况。是否有某种类型的侦听器可以扩展/实现,以了解为什么会发生关闭命令?

供将来参考:您可以为事件定义一个观察者方法,至少可以在关闭之前关闭所有打开的文件等。它不一定会给你一个关闭的理由,但这是一个开始

如果您说JVM进程是从外部终止的,那么可能有一个InterruptedException抛出到您可以捕获的地方。请注意,捕获InterruptedException而不重新中断线程在大多数情况下都是一个bug。在您的情况下,在调用线程“睡眠”时,您应该有秩序地关闭它。如果线程被中断,则有人希望取消执行。他们这样做可能有很好的理由;别以为你比他们知道得多


至少您可以在执行过程中的某个方便点定期检查线程的中断标志,以启动有序的任务关闭。

在您回复之前,我忘记了这个问题。原来是有人修改了舵图,修改了kubernetes的健康检查。我更新了配置文件以更正此问题。我还没有时间回去看看这个建议是否有效。
@Named
public class Importer implements Callable<String> {

  @Setter //lombok annotation
  private String filename;

  public void cleanUp() {
    log.info("PreDestroy - Importer");
    //clean up omitted
  }

  public String call() {
     List<String> content = //extract file content
     for(int i = 0; i < content.size; i++) {
       if (i+1 % 10000 == 0) {
         log.info("Processed {} rows in file {}", i+1, filename);
       }
       //rest of loop omitted
     }
  }
}
Processed 50000 rows in file test.txt
Processed 60000 rows in file text.txt
PreDestroy - Scheduler
PreDestroy - Importer
PreDestroy - Main
WELD-ENV-002001: Weld SE container 03128098-039d-46db-97e5-8538a52a38cc shut down