我从Spring Boot的关闭端点获得了200响应,我发现应用程序上下文按预期关闭,但随后JVM进程本身仍然存在。这是关闭端点的预期行为,还是预期进程本身也会正常终止?
在http://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-endpoints.html中,它表示关闭端点"允许应用程序正常关闭(默认情况下不启用)"。
答案 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-plugin
和start
目标的stop
,而不是使用关闭端点,以便在典型的集成测试方案中使用。
答案 2 :(得分:0)
如果您有预定的执行程序,则应指定destroy方法:
@Bean(destroyMethod = "shutdown")