编辑:事实证明,由于错误的健康检查失败,我的 docker 容器正在关闭。这导致 kubernetes 探测失败太多次并杀死了 pod。由于命令来自 JVM 外部,因此代码可能无法知道 JVM 周围的容器何时被杀死。留下这个问题,以防有人找到答案。
我有一个 Java SE 项目,它读取处理文件的参数。我正在使用 Weld-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 }
}
这是我的进口商代码
@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
}
}
}
文件 test.txt 大约有 100,000 行,因此我可以判断崩溃发生在文件处理过程中。因此,在我的代码运行几分钟后,我在日志末尾得到以下信息
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
我在调试级别记录“org.jboss”。我可以看到容器在处理文件的过程中被关闭,但我不明白它为什么会发生。是否有某种类型的侦听器可以扩展/实现以查看关闭命令发生的原因?