Spring Boot关闭端点是应该关闭整个JVM进程还是仅关闭应用程序上下文?

时间:2015-08-03 13:15:18

标签: spring-boot

我从Spring Boot的关闭端点获得了200响应,我发现应用程序上下文按预期关闭,但随后JVM进程本身仍然存在。这是关闭端点的预期行为,还是预期进程本身也会正常终止?

http://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-endpoints.html中,它表示关闭端点"允许应用程序正常关闭(默认情况下不启用)"。

3 个答案:

答案 0 :(得分:2)

感谢Stéphane,我发现在点击/ shutdown端点后阻止JVM进程终止的原因。我的一个依赖项中有一个ScheduledExecutor没有被应用程序上下文关闭,它阻止了JVM进程关闭(即使在应用程序上下文关闭后)。我写了一个简单的例子来说明如何重现行为,另一个例子展示了如何解决它。

当您点击/关闭端点时,此示例不会终止JVM进程:

@SpringBootApplication
public class AppSpringConfiguration {

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

    @Bean
    public ClassWithExecutor ce() {
        return new ClassWithExecutor();
    }

    @PostConstruct
    public void startScheduledTask() {
        ce().startScheduledTask();
    }

    @RestController
    public static class BusinessLogicController {

        @RequestMapping(value = "/hi")
        public String businessLogic() {
            return "hi";
        }
    }            

    public static class ClassWithExecutor {
        ScheduledExecutorService es;

        ClassWithExecutor() {
            this.es = Executors.newSingleThreadScheduledExecutor();
        }

        public void startScheduledTask() {
            es.scheduleAtFixedRate(new Runnable() {
                @Override
                public void run() {
                    System.out.println("Printing this every minute");
                }
            }, 0, 3, TimeUnit.SECONDS);
        }    
    }
}

通过添加一个在应用程序上下文关闭时关闭ScheduledExecutor的关闭钩子,JVM进程现在在命中/ shutdown端点后终止:

@SpringBootApplication
public class AppSpringConfiguration {

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

    @Bean
    public ClassWithExecutor ce() {
        return new ClassWithExecutor();
    }

    @Bean
    ShutdownAction sa() {
        return new ShutdownAction(ce());
    }

    @PostConstruct
    public void startScheduledTask() {
        ce().startScheduledTask();
    }

    @RestController
    public static class BusinessLogicController {

        @RequestMapping(value = "/hi")
        public String businessLogic() {
            return "hi";
        }
    }

    public static class ShutdownAction implements ApplicationListener<ContextClosedEvent> {
        private ClassWithExecutor classWithExecutor;

        ShutdownAction(ClassWithExecutor classWithExecutor) {
            this.classWithExecutor = classWithExecutor;
        }

        @Override
        public void onApplicationEvent(ContextClosedEvent event) {
            classWithExecutor.shutdown();
        }
    }

    public static class ClassWithExecutor {
        ScheduledExecutorService es;

        ClassWithExecutor() {
            this.es = Executors.newSingleThreadScheduledExecutor();
        }

        public void startScheduledTask() {
            es.scheduleAtFixedRate(new Runnable() {
                @Override
                public void run() {
                    System.out.println("Printing this every minute");
                }
            }, 0, 3, TimeUnit.SECONDS);
        }

        public void shutdown() {
            es.shutdownNow();
        }
    }
}

答案 1 :(得分:0)

除了Spring Boot应用程序之外,还有一些东西会阻止JVM退出。如果您没有,并且您有一个演示问题的示例项目,那么请创建一个问题,我们来看看。

您可以使用具有spring-boot-maven-pluginstart目标的stop,而不是使用关闭端点,以便在典型的集成测试方案中使用。

答案 2 :(得分:0)

如果您有预定的执行程序,则应指定destroy方法:

@Bean(destroyMethod = "shutdown")