【问题标题】:Running SpringBootApplication PostConstruct and PreDestroy运行 SpringBootApplication PostConstruct 和 PreDestroy
【发布时间】:2017-08-04 09:38:26
【问题描述】:

我在 docker 容器中运行 spring 应用程序时遇到问题(spring 和 docker 在我的环境中都有最新版本)。 我希望应用程序类 AnalysisServiceBootstrap 有一个健康的生命周期:在创建 AnalysisServiceBootstrap 之后使用方法 start() 运行初始化代码,并在破坏 AnalysisServiceBootstrap 之前运行方法 stop() (我想在有人时运行 stop() 代码停止应用程序)。

我有以下代码:

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);
    }
}

由于某种原因,我无法让方法 stop() 在 docker stop 上运行。 我尝试了 stackoverflow 和其他资源上提供的几种方法,但它们都不适合我。

我很高兴有适合您的代码(不仅仅是一些时尚建议)。

这几乎是我的 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} 

但请您在此处发布您拥有的任何工作 docker 文件。

非常感谢。

【问题讨论】:

  • 添加您的 Dockerfile 并展示您是如何创建容器(gradle 或 maven)
  • 请不要将其他信息添加为 cmets,而是编辑您的问题。
  • java 命令前加上exec 所以CMD exec java 这应该使它成为一个应该接收信号的后台进程。否则它会作为不接收信号的普通 bash 进程运行。另见ctl.io/developers/blog/post/…

标签: java spring docker spring-boot sigkill


【解决方案1】:

来自文档:

码头停运

停止一个或多个正在运行的容器 容器内的主进程会收到SIGTERM,经过一段宽限期后,SIGKILL

通过执行docker stop,您只是在杀死 java (Spring) 进程。

那么 Spring 上下文正确关闭的保证是什么?

在 Spring 应用程序中处理SIGTERM 的正确方法是添加关闭挂钩。

最终的代码应该是这样的:

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);
    }
}

该过程在以下问题中描述:

【讨论】:

  • Spring Boot 会自动注册一个关闭钩子,所以不需要这样做。但是,当收到 SIGKILL 时,再多的关闭挂钩也无济于事。
  • 它不是工作代码。你在那里调用 Thread 的 stop() 而不是调用我的类的 stop 。
  • @M.Deinum 关于SIGKILL 你是绝对正确的。那么解决方法是什么?
  • 您必须在容器中正确启动您的应用程序(但由于您没有将Dockerfile 添加到您难以回答的问题中。但问题可能出在那儿。
  • 我花了一整天的时间寻找它,也许有人会发现它也很有用(感谢 M. Deinum 的提示):对于 @PreDestroy 和 Dockerfile -> 确保使用 ENTRYPOINT 而不是 CMD 或 RUN - 仅然后您将应用程序作为主进程运行,SIGTERM 将被发送到您的应用程序
【解决方案2】:

向应用程序注册一个关闭挂钩,如此处所述 Spring Boot shutdown hook

每个 SpringApplication 都会向 JVM 注册一个关闭钩子,以确保 ApplicationContext 在退出时正常关闭。所有标准的 Spring 生命周期回调(例如 DisposableBean 接口,或 @PreDestroy 注解)都可以使用。

【讨论】:

    【解决方案3】:

    @PreDestroy 或实现 DisposableBean 的 destroy() 只有在我们执行 ctrl+c 或 docker stop 时才会执行。而如果我们执行 docker kill 或直接从 intelij IDE 停止它,它将不会执行

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-04-01
      • 1970-01-01
      • 2019-12-16
      • 1970-01-01
      • 1970-01-01
      • 2013-01-13
      • 1970-01-01
      相关资源
      最近更新 更多