简体   繁体   English

运行 SpringBootApplication PostConstruct 和 PreDestroy

[英]Running SpringBootApplication PostConstruct and PreDestroy

I have troubles with running spring application in docker container (both spring and docker have latest versions in my environment).我在 docker 容器中运行 spring 应用程序时遇到了麻烦(spring 和 docker 在我的环境中都有最新版本)。 I want to have healthy life cycle for application class AnalysisServiceBootstrap: to run initialization code with method start() right AFTER creation of AnalysisServiceBootstrap and also to run method stop() right BEFORE destruction of AnalysisServiceBootstrap (I want to run stop() code when someone stops the application).我希望应用程序类 AnalysisServiceBootstrap 拥有健康的生命周期:在创建 AnalysisServiceBootstrap 之后立即使用方法 start() 运行初始化代码,并在销毁 AnalysisServiceBootstrap 之前正确运行方法 stop()(我想在有人时运行 stop() 代码停止应用程序)。

I have following code:我有以下代码:

package com.pack;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.context.web.SpringBootServletInitializer;

@SpringBootApplication
public class AnalysisServiceBootstrap {

    // called OK on docker "start <containerId>"
    @PostConstruct
    public void start() throws Exception {
        // some init code
    }

    // NOT called on "docker stop <containerId>"
    @PreDestroy
    public void stop() {
       // some destroy code
    }

    public static void main(String[] args) {
        SpringApplication.run(AnalysisServiceBootstrap.class, args);
    }
}

For some reason I can not get method stop() running on docker stop.由于某种原因,我无法在 docker stop 上运行 stop() 方法。 I tried several ways offered on stackoverflow and other resources, but all of them did not work for me.我尝试了 stackoverflow 和其他资源上提供的几种方法,但所有这些方法都不适合我。

I will be glad to have code that works for you (not just some vogue suggestions).我很高兴有适合您的代码(不仅仅是一些时尚建议)。

Here is almost exact docker file of mine:这里几乎是我的 docker 文件:

FROM *********:6556/service-jvm

ARG SERVICE_JAR_FILE

ENV SERVICE_NAME service
ENV HTTP_PORT 603
ENV HTTPS_PORT 604
ENV SERVICE_JAR /opt/my/project/${SERVICE_JAR_FILE}
EXPOSE ${HTTP_PORT} ${HTTPS_PORT}
COPY ${SERVICE_JAR_FILE} /opt/my/project/${SERVICE_JAR_FILE}

CMD java -Xms1024m -Xmx1024m -dump:"/opt/my/project/dumppath" -javaagent:/opt/my/project/agent.jar -Djav.awt.headless=true -jar ${SERVICE_JAR} 

But you are invited to post here any working docker file that you have.但是我们邀请您在此处发布您拥有的任何可用的 docker 文件。

Thanks a lot.非常感谢。

From the documentation:从文档:

docker stop码头站

Stop one or more running containers The main process inside the container will receive SIGTERM , and after a grace period, SIGKILL停止一个或多个正在运行的容器 容器内的主进程会收到SIGTERM ,在一个宽限期后, SIGKILL

By executing docker stop you are just killing the java (Spring) process.通过执行docker stop您只是在杀死 java (Spring) 进程。

So what are the guarantees that Spring context will shutdown properly?那么 Spring 上下文将正确关闭的保证是什么?

The right way to handle SIGTERM in Spring applications is to add shutdown hook.在 Spring 应用程序中处理SIGTERM的正确方法是添加关闭钩子。

The final code should look like this:最终代码应如下所示:

package com.pack;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.context.web.SpringBootServletInitializer;

@SpringBootApplication
public class AnalysisServiceBootstrap {

    @PostConstruct
    public void start() throws Exception {
        // some init code
    }

    @PreDestroy
    public void tearDown() {
       // some destroy code
    }

    public static void main(String[] args) {
        Runtime.getRuntime().addShutdownHook(new Thread() {
            @Override
            public void run() {
                // write here any instructions that should be executed
                tearDown();
            }   
        });


        SpringApplication.run(AnalysisServiceBootstrap.class, args);
    }
}

The process is described in the following questions:该过程在以下问题中描述:

Register a shutdown hook to the application as mentioned here Spring Boot shutdown hook如此处所述,向应用程序注册关闭挂钩Spring Boot 关闭挂钩

Each SpringApplication will register a shutdown hook with the JVM to ensure that the ApplicationContext is closed gracefully on exit.每个 SpringApplication 都会向 JVM 注册一个关闭钩子,以确保 ApplicationContext 在退出时正常关闭。 All the standard Spring lifecycle callbacks (such as the DisposableBean interface, or the @PreDestroy annotation) can be used.可以使用所有标准的 Spring 生命周期回调(例如 DisposableBean 接口或 @PreDestroy 注释)。

@PreDestroy or implementing the destroy() of DisposableBean gets executed only when we do ctrl+c or docker stop <>. @PreDestroy 或实现 DisposableBean 的 destroy() 仅在我们执行 ctrl+c 或 docker stop <> 时才会执行。 whereas it won't execute if we do docker kill <> or stopping it directly from intelij IDE而如果我们执行 docker kill <> 或直接从 intelij IDE 停止它,它将不会执行

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM