Created
December 4, 2017 08:46
-
-
Save chenqiyue/d720a96990c2901691ecb1f2fa56ae7d to your computer and use it in GitHub Desktop.
Spring boot Tomcat GracefulShutdown
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.laobai.boot.tomcat; | |
import org.apache.catalina.connector.Connector; | |
import org.springframework.boot.context.embedded.tomcat.TomcatConnectorCustomizer; | |
import org.springframework.context.ApplicationListener; | |
import org.springframework.context.event.ContextClosedEvent; | |
import java.util.concurrent.Executor; | |
import java.util.concurrent.ThreadPoolExecutor; | |
import java.util.concurrent.TimeUnit; | |
import lombok.extern.slf4j.Slf4j; | |
/** | |
* @author cqy | |
* @since 2017/11/6. | |
*/ | |
@Slf4j | |
public class TomcatGracefulShutdown implements TomcatConnectorCustomizer, ApplicationListener<ContextClosedEvent> { | |
final long shutdownTimeout; | |
final TimeUnit unit; | |
private volatile Connector connector; | |
public TomcatGracefulShutdown(long shutdownTimeout, TimeUnit unit) { | |
this.shutdownTimeout = shutdownTimeout; | |
this.unit = unit; | |
} | |
@Override | |
public void customize(Connector connector) { | |
this.connector = connector; | |
} | |
@Override | |
public void onApplicationEvent(ContextClosedEvent event) { | |
if (this.connector == null) { | |
return; | |
} | |
awaitTermination(this.connector); | |
} | |
void awaitTermination(Connector connector) { | |
connector.pause(); | |
Executor executor = connector.getProtocolHandler().getExecutor(); | |
if (executor instanceof ThreadPoolExecutor) { | |
log.warn("Context closed. Going to await termination for $shutdownTimeout $unit."); | |
try { | |
ThreadPoolExecutor ex = (ThreadPoolExecutor) executor; | |
ex.shutdown(); | |
if (!ex.awaitTermination(shutdownTimeout, unit)) { | |
log.warn("Tomcat thread pool did not shut down gracefully within $shutdownTimeout $unit. " + | |
"Proceeding with forceful shutdown"); | |
} | |
} catch (InterruptedException e){ | |
Thread.currentThread().interrupt(); | |
} | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.laobai.boot.tomcat; | |
import org.apache.catalina.startup.Tomcat; | |
import org.springframework.beans.factory.annotation.Value; | |
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; | |
import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer; | |
import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory; | |
import org.springframework.context.annotation.Bean; | |
import org.springframework.context.annotation.Configuration; | |
import java.util.concurrent.TimeUnit; | |
import javax.servlet.Servlet; | |
/** | |
* @author cqy | |
* @since 2017/11/6. | |
*/ | |
@Configuration | |
@ConditionalOnClass({Servlet.class, Tomcat.class}) | |
public class TomcatGracefulShutdownAutoConfiguration { | |
@Value("${catalina.threadpool.execution.timeout.seconds:30}") | |
long shutdownTimeoutSeconds; | |
@Bean | |
TomcatGracefulShutdown gracefulShutdown() { | |
return new TomcatGracefulShutdown(shutdownTimeoutSeconds, TimeUnit.SECONDS); | |
} | |
@Bean | |
EmbeddedServletContainerCustomizer tomcatCustomizer() { | |
return container -> { | |
if (container instanceof TomcatEmbeddedServletContainerFactory) { | |
((TomcatEmbeddedServletContainerFactory) container).addConnectorCustomizers(gracefulShutdown()); | |
} | |
}; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment