Spring Boot 1.0 Web服务优雅下线
Web服务优雅下线定义
- 停止接收新的服务
- 已经接收的请求正常处理并返回
- 停止应用
环境约束
- Spring Boot 1.5.9.RELEASE
- undertow 1.4.21.Final
实现方案
方案一,使用SpringApplication.exit(applicationContext)方法
方案二,调用spring-boot-actuator的shutdown端点
方案三,利用undertow的GracefulShutdownHandler类的shutdown方法
结论
直接使用方案一、方案二不能实现“Web服务优雅下线定义”的第2点,不能实现优雅下线。先实现方案三,再利用方案一或方案二可以实现优雅下线。
方案一,使用SpringApplication.exit(applicationContext)方法
这个方法其实封装的是ApplicationContext的close方法,支持自定义exitCode,并且在关闭前会发布ExitCodeEvent事件。
方案二,调用spring-boot-actuator的shutdown端点
启用shutdown端点需要如下配置:
- pom文件引入spring-boot-starter-actuator
- bootstrap.yml或application.yml增加
management:
security:
enabled: false
endpoints:
shutdown:
enabled: true
shutdown端点也是利用ApplicationContext的close方法实现停止应用。具体源码见org.springframework.boot.actuate.endpoint.ShutdownEndpoint#invoke
方案三,利用undertow的GracefulShutdownHandler类的shutdown方法
前面2种方案会直接停止应用,导致已经接收的请求不能正确处理并返回;Spring Boot没有提供现成的方法优雅地停止Web服务,但我们可以利用undertow提供的机制和GracefulShutdownHandler来实现undertow这一Web服务的优雅下线。自定义代码如下,
@Bean
public GracefulShutdownUndertow GracefulUndertowShutdown() {
return new GracefulShutdownUndertow();
}
@Bean
public UndertowEmbeddedServletContainerFactory servletWebServerFactory(GracefulShutdownUndertow gracefulShutdownUndertow) {
UndertowEmbeddedServletContainerFactory factory = new UndertowEmbeddedServletContainerFactory();
factory.addDeploymentInfoCustomizers(deploymentInfo -> deploymentInfo.addInitialHandlerChainWrapper(gracefulShutdownUndertow));
return factory;
}
private static class GracefulShutdownUndertow implements ApplicationListener<ContextClosedEvent>, HandlerWrapper {
private volatile GracefulShutdownHandler handler;
@Override
public void onApplicationEvent(ContextClosedEvent contextClosedEvent){
try{
this.handler.shutdown();
this.handler.awaitShutdown(30000);
}catch (Exception e){
e.printStackTrace();
}
}
@Override
public HttpHandler wrap(HttpHandler httpHandler) {
this.handler = new GracefulShutdownHandler(httpHandler);
return this.handler;
}
}
原理:undertow的WEB容器由UndertowEmbeddedServletContainerFactory负责创建。我们通过自定义UndertowEmbeddedServletContainerFactory这个Bean,向其中增加GracefulShutdownHandler;这样在应用停止时,GracefulShutdownUndertow收到ContextClosedEvent事件,触发GracefulShutdownHandler的shutdown方法,实现undertow容器的正常关闭,进而实现整个服务优雅下线。