JVM优雅停机机制
关于优雅停机,JVM提供了一个叫做ShutdownHook的东东,什么意思呢?就是说我们的应用程序只要在程序中向JVM注册了这个东东,JVM就会在收到关机信号(非kill -9)时,JVM就会在真正调用关机之前执行你注册在ShutdownHook里的东东,以达到程序在关闭前释放掉各种资源的目的。
注册方式:
注册ShutdownHook
Runtime.getRuntime().addShutdownHook(Thread thread)
解决的问题
dubbo在其类AbstractConfig里面注册了ShutdownHook:
SpringBoot中则在应用run之后刷新上下文时注册ShutdownHook:
故应用程序在收到关机信号(非kill -9)时,JVM会同时启动两个线程来分别运行Dubbo和SpringBoot的停机工作,Dubbo和SpringBoot自身都实现了自身的优雅停机,但是由于Dubbo和SpringBoot的整合,使得如果dubbo在优雅停机过程中处理未处理完请求时SpringBoot已完成关机时服务端和客户端就会产生大量错误,我们的优雅停机就是要解决这样的问题。
解决思路
由于Dubbo自身优雅停机过程中可能会依赖SpringBoot的组件,SpringBoot在SpringBootApplication中提供了取消自身注册ShutdonwHook的机制,如下:
那么,大体思路就是取消掉SpringBoot自身的ShutdownHook注册,为SpringBoot注册一个ShutdownHook,让SpringBoot在等待一定时间(等待Dubbo先关闭)后,在关闭SpringBoot容器。
具体代码
package com.xyy.crm.query.consumer.shutdown;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
/**
* @author gelong
*/
@Component
public class GracefullyShutdownHook {
private final Logger logger = LoggerFactory.getLogger(GracefullyShutdownHook.class);
@Autowired
private ConfigurableApplicationContext configurableApplicationContext;
@Value("${spring.dubbo.service.shutdown.wait}")
private long dubboShutdownWait;
@PostConstruct
public void registerShutdownHook() {
logger.info("[SpringShutdownHook] Register ShutdownHook....");
Runnable shutdownHook = () -> {
try {
logger.info("[SpringShutdownHook] Application need sleep {} seconds to wait Dubbo shutdown", (double)dubboShutdownWait / 1000.0D);
Thread.sleep(dubboShutdownWait);
logger.info("[SpringShutdownHook] ApplicationContext closed start, Application shutdown doing");
this.configurableApplicationContext.close();
logger.info("[SpringShutdownHook] ApplicationContext closed, Application shutdown");
} catch (InterruptedException var2) {
logger.error(var2.getMessage(), var2);
}
};
Runtime.getRuntime().addShutdownHook(new Thread(shutdownHook));
}
}
注:
dubboShutdownWait为配置的等待Dubbo关闭时长,单位为ms,此值Dubbo官网给出的缺省值是10000ms,具体自定。
参考文档
https://blog.csdn.net/liubenlong007/article/details/79958076