本文主要是介绍spring boot不同版本的优雅关闭(graceful shutdown)和在windows下winsw服务方式运行的配置,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
起因
- spring boot默认是不会优雅关闭的,这样就导致在重启时会将正在运行的程序打断,导致故障发生。
当前解决方式
- 引入
spring-boot-starter-actuator
监控类库,它其中一个功能支持优雅关闭。
- spring boot 2.3版本开始,自己集成了优雅关闭,无需再引入上方类库即可实现优雅关闭。
坑爹的地方
spring-boot-starter-actuator
文档中说是支持优雅关闭,但仅仅是spring层面上的,不和tomcat等容器挂钩,直到spring boot 2.3开启自带的优雅关闭后才真正能实现,也就是说2.3之前的版本根本实现不了优雅关闭,需要自己来进一步按照使用的容器做处理才行,参考这个issue:Allow the embedded web server to be shut down gracefully。
- 2.3以上版本,如果是在linux下,发送命令
kill -2 xxx
可以触发优雅关闭,但是在windows下,只有ctrl+c
才能触发(可以在idea下用run里面的exit
按钮模拟),但windows下我们一般是用服务来运行,所以永远无法触发ctrl+c
,因此即便是2.3版本后,windows下也必须安装spring-boot-starter-actuator
来通过发送http请求来实现优雅关闭。
2.3以上版本的处理方法(如果是用tomcat容器需要9.0.33以上)
2.3以下的处理方法(或者是2.3版本以上的windows端)
- 引入
spring-boot-starter-actuator
的maven类库<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
- 在
application.yml
中增加:#监控相关配置
management:
endpoint:
# 开启
shutdown:
enabled: true
endpoints:
web:
# 只允许shutdown,为了安全,其它想要监控自行配置
exposure:
include: "shutdown"
# 自定义请求路径,为了安全
base-path: /xxx
server:
#自定义请求端口,为了安全
port: 7080
发送请求的路径是这样的:curl -X POST http://localhost:自定义端口/自定义路径/shutdown
,由于路径和端口都是自定义的,所以安全性方面不用太过担心。
- 分支1:如果是2.3版本以上的windows端,再开启自带的优雅关闭,就可以通过http请求来实现了
# 开启优雅关闭
server:
shutdown: graceful
# 配置强制结束时间,不配置的话默认30s
spring:
lifecycle:
timeout-per-shutdown-phase: 30s
- 分支2:如果是2.3以下版本,此时虽然可以发送http请求来关闭,但实际上不会等待正在执行的程序,而是会直接关闭,还应该配置容器相关,以tomcat容器为例:
- 创建相关类:
package xxx.xxx.xxx;
import lombok.extern.slf4j.Slf4j;
import org.apache.catalina.connector.Connector;
import org.springframework.boot.web.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;
/**
* 优雅关闭
*/
@Slf4j
public class GracefulShutdown implements TomcatConnectorCustomizer,
ApplicationListener<ContextClosedEvent> {
private volatile Connector connector;
/**
* 15s强制关闭
*/
private static final int TIMEOUT = 15;
/**
* 自定义链接
*
* @param connector
*/
@Override
public void customize(Connector connector) {
this.connector = connector;
}
/**
* 关闭时触发
*
* @param event
*/
@Override
public void onApplicationEvent(ContextClosedEvent event) {
this.connector.pause();
Executor executor = this.connector.getProtocolHandler().getExecutor();
if (executor instanceof ThreadPoolExecutor) {
try {
ThreadPoolExecutor threadPoolExecutor = (ThreadPoolExecutor) executor;
threadPoolExecutor.shutdown();
if (!threadPoolExecutor.awaitTermination(TIMEOUT, TimeUnit.SECONDS)) {
log.warn("Tomcat thread pool did not shut down gracefully within "
+ "30 seconds. Proceeding with forceful shutdown");
}
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
}
}
package xx.xxx.xxx;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
import org.springframework.context.annotation.Bean;
@SpringBootApplication
public class XxxxApplication {
/**
* 优雅关闭bean
* @return
*/
@Bean("gracefulShutdown")
public GracefulShutdown gracefulShutdown() {
return new GracefulShutdown();
}
/**
* tomcat配置优雅关闭
* @param gracefulShutdown
* @return
*/
@Bean
public ConfigurableServletWebServerFactory webServerFactory(@Qualifier("gracefulShutdown") GracefulShutdown gracefulShutdown) {
TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
factory.addConnectorCustomizers(gracefulShutdown);
return factory;
}
public static void main(String[] args) {
SpringApplication.run(XxxxApplication .class, args);
}
}
- 以上配置后再发送http请求才会优雅关闭,但仅适用于tomcat容器,undertow容器可以参考这个:Spring boot 2.0 之优雅停机
windows端用winsw设置为服务运行时的配置
- winsw可以从这里下载:winsw,主要作用就是可以让程序以服务的方式后台运行并能开机启动等
- 需要下载windows下的curl,地址:curl for Windows
- 配置winsw的config文件:
<service>
<!-- ID of the service. It should be unique across the Windows system-->
<id>XXX</id>
<!-- Display name of the service -->
<name>xxx</name>
<!-- Service description -->
<description>xxx名称(powered by WinSW)</description>
<!-- Path to the executable, which should be started -->
<env name="JAVA_HOME" value="%JAVA_HOME%"/>
<executable>java</executable>
<startarguments>-jar -Xms128m -Xmx512m "D:\jar包路径\xxx.jar"</startarguments>
<!--停止 -->
<stopexecutable>D:\curl路径\bin\curl.exe</stopexecutable>
<stoparguments>-X POST http://localhost:7080/xxx/shutdown</stoparguments>
<!--不配置的话默认15s-->
<stoptimeout>30 sec</stoptimeout>
<startmode>Automatic</startmode>
<logmode>none</logmode>
</service>
结束
这篇关于spring boot不同版本的优雅关闭(graceful shutdown)和在windows下winsw服务方式运行的配置的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!