1.实现SignalHandler
在进程被kill时收到TERM信号,对main函数的运行不会有任何影响
public class GracefulShutdownHandler implements SignalHandler {
public void registerSignal(String signalName) {
Signal signal = new Signal(signalName);
Signal.handle(signal, this);
}
@Override
public void handle(Signal signal) {
switch (signal.getName()) {
case "TERM":
//
break;
case "INT":
//
break;
default:
}
}
}
2.ShutdownHook
在进程被kill的时候main函数就已经结束,仅会运行shutdownHook中run()方法的代码。
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
//
}
});
3.SpringBoot优雅关闭
实现TomcatConnectorCustomizer接口,用于注入tomcat的connector,tomcat通过connector接受请求
public class GracefulShutdown implements TomcatConnectorCustomizer, ApplicationListener<ContextClosedEvent> {
private volatile Connector connector;
private final int waitTime = 20;
/**
* 实现TomcatConnectorCustomizer接口,用于获取tomcat用于接收请求的connector
*/
@Override
public void customize(Connector connector) {
this.connector = connector;
}
/**
* 实现ApplicationListener<ContextClosedEvent>接口,用于监听应用的关闭事件
*/
@Override
public void onApplicationEvent(ContextClosedEvent event) {
// tomcat通过connector接收请求,当服务停止时先将connector停止,不接受新的请求
this.connector.pause();
java.util.concurrent.Executor executor = this.connector.getProtocolHandler().getExecutor();
if (executor instanceof ThreadPoolExecutor) {
try {
ThreadPoolExecutor threadPoolExecutor = (ThreadPoolExecutor) executor;
threadPoolExecutor.shutdown();
if (!threadPoolExecutor.awaitTermination(waitTime, TimeUnit.SECONDS)) {
log.warn("Tomcat thread pool did not shut down gracefully within "
+ waitTime + " seconds. Proceeding with forceful shutdown");
}
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
// 关闭其他....
}
}
SpringBoot 1.5.x
/**
* 用于注入 connector
*/
@Bean
public EmbeddedServletContainerCustomizer tomcatCustomizer() {
return new EmbeddedServletContainerCustomizer() {
@Override
public void customize(ConfigurableEmbeddedServletContainer container) {
if (container instanceof TomcatEmbeddedServletContainerFactory) {
((TomcatEmbeddedServletContainerFactory) container).addConnectorCustomizers(gracefulShutdown());
}
}
};
}
SpringBoot 2.x.x
/**
* tomcat connector注入到GracefulShutdownHandler
*/
@Bean
public WebServerFactoryCustomizer webServerFactoryCustomizer() {
return new WebServerFactoryCustomizer() {
@Override
public void customize(WebServerFactory factory) {
if (factory instanceof TomcatServletWebServerFactory) {
((TomcatServletWebServerFactory) factory).addConnectorCustomizers(gracefulShutdownHandler());
}
}
};
}