我正在开发一个由嵌入式Tomcat支持的Spring Boot应用程序,我需要通过以下步骤来正常关闭:
*依次(依次)执行上述步骤
我该如何实现?
P.S。 Spring Boot 1.5.20.RELEASE,Java 8
答案 0 :(得分:2)
我最终得到了:
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import org.apache.catalina.connector.Connector;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.context.embedded.tomcat.TomcatConnectorCustomizer;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextClosedEvent;
public class GracefulShutdown implements TomcatConnectorCustomizer, ApplicationListener<ContextClosedEvent> {
private static final Logger log = LoggerFactory.getLogger(GracefulShutdown.class);
private volatile Connector connector;
@Override
public void customize(Connector connector) {
this.connector = connector;
}
@Override
public void onApplicationEvent(ContextClosedEvent contextClosedEvent) {
log.info("Protocol handler is shutting down");
this.connector.pause();
Executor executor = this.connector.getProtocolHandler().getExecutor();
if (executor instanceof ThreadPoolExecutor) {
try {
ThreadPoolExecutor threadPoolExecutor = (ThreadPoolExecutor) executor;
threadPoolExecutor.shutdown();
if (!threadPoolExecutor.awaitTermination(30, TimeUnit.SECONDS))
log.warn("Tomcat thread pool did not shut down gracefully within 30 seconds. Proceeding with forceful shutdown");
else
log.info("Protocol handler shut down");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
}
更多其他豆:
import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory;
import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
...
@Bean
public GracefulShutdown gracefulShutdown() {
return new GracefulShutdown();
}
@Bean
public EmbeddedServletContainerFactory servletContainer(final GracefulShutdown gracefulShutdown) {
TomcatEmbeddedServletContainerFactory factory = new TomcatEmbeddedServletContainerFactory();
factory.addConnectorCustomizers(gracefulShutdown);
return factory;
}
...
答案 1 :(得分:0)
关于马修一世。 请注意,他应该使用JDK'ThreadPoolExecutor',而他应该使用Tomcat ThreadPoolExecutor。 ==>'org.apache.tomcat.util.threads.ThreadPoolExecutor;
否则,关闭挂钩将不会真正等待Tomcat线程停止。
答案 2 :(得分:0)
它很简单,Spring boot本身提供了功能。 https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-application-exit
void shoutdown(){
System.out.println("====+= Shoutdown +++===");
System.exit(SpringApplication.exit(apc, this.exitCodeGenerator()));
}
您可以在输出中看到所有当前线程都已关闭。 输出:
==== + =关机+++ ===
答案 3 :(得分:0)
Spring Boot 2.3(于2020年5月发布)中添加了正常关机支持。这样可以在关闭上下文并关闭容器之前完成活动请求。
所有四个嵌入式Web服务器(Jetty,Reactor Netty,Tomcat和Undertow)以及响应式和基于Servlet的Web应用程序都支持正常关机。使用
server.shutdown=graceful
启用后,关闭时,Web服务器将不再允许新请求,并将等待宽限期以完成活动请求。宽限期可以使用spring.lifecycle.timeout-per-shutdown-phase
进行配置。
因此,启用正常关机后,应用程序将在关机时依次执行以下步骤:
server.shutdown=graceful
添加到属性中(默认情况下,它设置为immediate
)。spring.lifecycle.timeout-per-shutdown-phase
属性进行配置(例如:spring.lifecycle.timeout-per-shutdown-phase=1m
。对于Spring Boot <2.3,您将修改服务器的连接器以停止接受新请求,如this Spring GitHub issue中所述。