SpringBoot2.3新特性优雅停机详解
简介
在以往的项目中,我们在正常停止服务时,往往都是使用kill
的方式来停止,这种方式虽然简单,但是可能会导致一些问题,比如程序被强制关闭时,可能会导致正在处理的请求直接中断等问题。SpringBoot2.3中新增了一个优雅停机的功能,可以让我们在停止服务时,更加安全和优雅。
优雅停机的原理
在之前的SpringBoot版本中,当我们使用kill
命令关闭程序时,操作系统都是直接向程序发送SIGTERM
信号,让程序进行退出。但是在SpringBoot2.3中,程序会在收到SIGTERM
信号时,进行优雅停机操作,它的流程如下:
- 在收到
SIGTERM
信号后,程序会停止接收新的请求。 - 当所有正在处理的请求处理完毕后,程序会优雅退出。
使用示例
下面是两个使用示例:
示例1:使用默认的优雅停机配置
在SpringBoot2.3中,我们只需要在application.properties
配置文件中添加下面的配置,即可使用默认的优雅停机功能:
server.shutdown=graceful
同时,在我们的Java代码中,可以在SpringApplication.run
方法中添加下面的内容,来手动触发关闭程序:
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication application = new SpringApplication(Application.class);
ConfigurableApplicationContext context = application.run(args);
// 注册关闭钩子
context.registerShutdownHook();
}
}
这样,在关闭程序时,程序会自动触发优雅停机操作。
示例2:自定义优雅停机配置
如果需要自定义优雅停机的配置,我们需要创建一个实现了GracefulShutdown
接口的类,然后在application.properties
配置文件中添加下面的配置:
server.shutdown=graceful
spring.lifecycle.timeout-per-shutdown-phase=30s
其中,GracefulShutdown
接口有两个方法,分别是shutdown()
和getPhase()
。shutdown()
方法中是自定义的优雅关闭逻辑,getPhase()
方法则是返回一个数值,表示该关闭操作的阶段。
下面是一个示例:
@Configuration
public class GracefulShutdownConfig {
@Bean
public GracefulShutdown gracefulShutdown() {
return new GracefulShutdown();
}
private class GracefulShutdown implements GracefulShutdownCallback, GracefulShutdown {
private final Logger logger = LoggerFactory.getLogger(GracefulShutdown.class);
private volatile boolean isShuttingDown = false;
private final AtomicInteger shutdownCount = new AtomicInteger(0); // 统计关闭请求次数
private CountDownLatch shutDownLatch = new CountDownLatch(1);
@Override
public void shutdown() {
if (!this.isShuttingDown) {
this.isShuttingDown = true;
logger.info("Shutdown is being called......");
Thread td = new Thread(() -> {
// 判断是否还有未完成的请求
int loopCount = 0;
while (true) {
if(Service.getIsFinished()) {
break;
}else if(shutdownCount.get() == 1) {
Service.finish();
}else if(loopCount >= 60) {
logger.info("Timeout exit because of 60 loops check finished");
Service.finish();
}else {
logger.info("wait for all services finish up......num of task unfinish : {}", Service.getTaskCount() - Service.getFinishCount());
try {
Thread.sleep(1000L);
loopCount += 1;
} catch (InterruptedException e) {
logger.error("Close sleep exception {}", e.getMessage());
}
}
}
// 关闭服务器
shutDownLatch.countDown();
});
td.setDaemon(false);
td.start();
}
try {
shutDownLatch.await(30, TimeUnit.SECONDS);
logger.info("Shutdown is finished......");
} catch (InterruptedException e) {
logger.error("Close Timing out Eclipse processes: ", e);
}
}
@Override
public int getPhase() {
return Integer.MAX_VALUE; // 返回一个较大的数字,保证该操作是最后一步执行
}
@Override
public String toString() {
return this.getClass().getSimpleName();
}
}
}
在该示例中,我们定义了一个GracefulShutdownConfig
配置类,其中包含一个实现了GracefulShutdown
接口的GracefulShutdown
内部类。在shutdown()
方法中,我们进行了自定义的关闭逻辑,首先判断程序中是否还有未完成的请求,如果有,则等待请求完成,然后在关闭服务器;如果无未完成的请求,则直接关闭服务器。
在getPhase()
中,我们返回了一个较大的数字,保证该操作是在其他关闭操作完成后,最后一个执行。
总结
SpringBoot2.3中添加了优雅停机的功能,可以让我们在关闭程序时更加安全和优雅。我们可以使用默认的配置,也可以进行自定义配置。在自定义配置时,我们需要创建一个实现了GracefulShutdown
接口的类,在其中编写自己的优雅停机逻辑。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:SpringBoot2.3新特性优雅停机详解 - Python技术站