我的项目是从SpringBoot2.0.4( Java 8)转到SpringBoot2.1.0( Java 11 )。当应用程序使用Spring 2.0.4和Java 8构建并在Docker / Docker组合中运行时,调用了@PostConstruct-annotated方法,但是在迁移到SpringBoot2.1.0和Java 11之后,@PreDestroy-annotated方法不再被调用。
我尝试过从注释切换到实现InitializingBean和DisposableBean,就像描述的这里那样,但是DisposableBean.destroy方法没有被调用。
我还尝试将依赖项添加到javax.批注-api版本1.3.2中,结果是相同的。
如何复制:
使用生命周期bean创建一个最小的Spring应用程序:
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;
@Component
public class Life implements InitializingBean, DisposableBean {
@Override
public void destroy() throws Exception {
System.out.println("--- Life.shutdown");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("--- Life.startup");
}
}从目标子文件夹启动Spring应用程序:
cd target
java -jar demo-0.0.1-SNAPSHOT.jar当应用程序使用Ctrl+C停止时,将调用DisposableBean.destroy。
返回到父文件夹:
cd ..使用Maven启动Spring应用程序:
mvn spring-boot:run当应用程序使用Ctrl+C停止时,将调用DisposableBean.destroy。
Dockerfile:
FROM openjdk:11.0.1-jre-slim
COPY target/*.jar app.jar
EXPOSE 8080
ENTRYPOINT java -jar /app.jar生成、运行和停止Docker映像:
docker build -t demo .
docker run -p 8080:8080 demo
docker ps
docker stats 3ca5b804ab13
docker stop 3ca5b804ab13
docker logs 3ca5b804ab13当应用程序使用停靠器停止停止时,不会调用DisposableBean.destroy。
docker-compose.yml:
demo:
image: demo
ports:
- '8080:8080'使用Docker运行Docker映像(模拟OpenShift):
docker-compose up
docker-compose down
demo_demo_1 exited with code 137当应用程序使用docker停止时,不会调用DisposableBean.destroy。
我怀疑Docker在发布SIGKILL之前正在尝试SIGTERM,因为在容器被杀死之前有10秒的延迟。
发布于 2018-12-03 07:28:27
我想我找到了解决方案(在这个博客条目中):在Dockerfile中使用exec表单而不是shell表单,这样Docker发出的SIGTERM就会命中java进程,而不是bash进程(它不会向任何子进程转发信号)。
ENTRYPOINT java -jar /app.jarENTRYPOINT ["java", "-jar", "/app.jar"]发布于 2018-11-30 07:41:59
有许多地方的设置可能出错。首先,我建议确定java/spring部分是否存在某些问题,还是与坞/环境相关的问题。从这个问题上看,它听起来像是与java相关的,但实际上我怀疑它不是在java/spring中。
因此,mvn spring-boot:run按预期工作,我看到您将spring引导应用程序打包为jar (app.jar),很可能使用了一个spring引导插件。这也是可能出错的地方,因为spring引导使用特殊的类加载器在运行时加载东西。
因此,为了完全消除" java /spring“部分,导航到您的target目录并运行java -jar app.jar (当然,确保在本地计算机上安装了java 11 )。如果它不工作-调查java /spring部件,否则继续进行对接部分。
应用程序很有可能会像预期的那样工作。
现在,关于码头设置。在运行docker组合并看到它失败之后,
您可以使用以下命令:
docker ps -a // -a flag to see container ids of containers that were stopped for whatever reason as well.现在,获取退出的java进程的Id并检查其日志:
docker logs <ID_OF_THE_EXTED_CONTAINER_GOES_HERE> 现在,应用程序上下文可能无法启动(可能是与网络相关的问题或其他问题,在这里,如果不看到实际的日志,很难判断),因此出现了问题。
另一个可能的问题是,应用程序“太重”(我的意思是它超出了码头集装箱的某些配额)。
您可以运行docker stats <CONTAINER_ID>命令来实时查看其内存/ cpu的使用情况,或者从应用程序中收集指标。
https://stackoverflow.com/questions/53540579
复制相似问题