一、前言

创新互联建站主营徽县网站建设的网络公司,主营网站建设方案,成都App定制开发,徽县h5成都小程序开发搭建,徽县网站营销推广欢迎徽县等地区企业咨询
在我们进行系统升级的时候,往往需要关闭我们的应用,然后重启。在关闭应用前,我们希望做一些前置操作,比如关闭数据库、redis连接,清理zookeeper的临时节点,释放分布式锁,持久化缓存数据等等。
二、Linux的信号机制
在linux上,我们关闭进程主要是使用 kill 的方式。
当执行该命令以后,linux会向进程发送一个信号,进程收到以后之后,可以做一些清理工作。
kill 命令默认的信号值为 15 ,即 SIGTERM 信号。
通过 kill -l 查看linux支持哪些信号:
linux提供了 signal() api,可以将信号处理函数注册上去:
- #include
 - #include
 - #include
 - #include
 - #include
 - static void gracefulClose(int sig)
 - {
 - printf("执行清理工作\n");
 - printf("JVM 已关闭\n");
 - exit(0); //正常关闭
 - }
 - int main(int argc,char *argv[])
 - {
 - if(signal(SIGTERM,gracefulClose) == SIG_ERR)
 - exit(-1);
 - printf("JVM 已启动\n");
 - while(true)
 - {
 - // 执行工作
 - sleep(1);
 - }
 - }
 
三、Java提供的Shutdown Hook
Java并不支持类似于linux的信号机制,但是提供了 Runtime.addShutdownHook(Thread hook) 的api。
在JVM关闭前,会并发执行各个Hook线程。
- public class ShutdownHook {
 - public static void main(String[] args) throws InterruptedException {
 - Runtime.getRuntime().addShutdownHook(new DbShutdownWork());
 - System.out.println("JVM 已启动");
 - while(true){
 - Thread.sleep(10L);
 - }
 - }
 - static class DbShutdownWork extends Thread{
 - public void run(){
 - System.out.println("关闭数据库连接");
 - }
 - }
 - }
 
四、Spring Boot提供的优雅关闭功能
我们一般采用如下的方式,启动一个Spring boot应用:
- public static void main(String[] args) throws Exception {
 - SpringApplication.run(SampleController.class, args);
 - }
 
SpringApplication.run()代码如下,会调用到refreshContext(context)方法:
- public ConfigurableApplicationContext run(String... args) {
 - StopWatch stopWatch = new StopWatch();
 - stopWatch.start();
 - ConfigurableApplicationContext context = null;
 - FailureAnalyzers analyzers = null;
 - configureHeadlessProperty();
 - SpringApplicationRunListeners listeners = getRunListeners(args);
 - listeners.started();
 - try {
 - ApplicationArguments applicationArguments = new DefaultApplicationArguments(
 - args);
 - ConfigurableEnvironment environment = prepareEnvironment(listeners,
 - applicationArguments);
 - Banner printedBanner = printBanner(environment);
 - context = createApplicationContext();
 - analyzers = new FailureAnalyzers(context);
 - prepareContext(context, environment, listeners, applicationArguments,
 - printedBanner);
 - refreshContext(context);
 - afterRefresh(context, applicationArguments);
 - listeners.finished(context, null);
 - stopWatch.stop();
 - if (this.logStartupInfo) {
 - new StartupInfoLogger(this.mainApplicationClass)
 - .logStarted(getApplicationLog(), stopWatch);
 - }
 - return context;
 - }
 - catch (Throwable ex) {
 - handleRunFailure(context, listeners, analyzers, ex);
 - throw new IllegalStateException(ex);
 - }
 - }
 
refreshContext()方法比较简单:
- private void refreshContext(ConfigurableApplicationContext context) {
 - refresh(context); //调用ApplicationContext.refresh()
 - if (this.registerShutdownHook) { //registerShutdownHook默认值为true
 - try {
 - context.registerShutdownHook();
 - }
 - catch (AccessControlException ex) {
 - // Not allowed in some environments.
 - }
 - }
 - }
 
AbstractApplicationContext.registerShutdownHook()代码:
- public void registerShutdownHook() {
 - if (this.shutdownHook == null) {
 - this.shutdownHook = new Thread() {
 - @Override
 - public void run() {
 - synchronized (startupShutdownMonitor) {
 - doClose();
 - }
 - }
 - };
 - Runtime.getRuntime().addShutdownHook(this.shutdownHook);
 - }
 - }
 
很明显,Spring boot通过在启动时,向JVM注册一个ShutdownHook,从而实现JVM关闭前,正常关闭Spring容器。而Spring在销毁时,会依次调用bean的destroy动作来销毁。
五、Dubbo的优雅关闭策略
Dubbo同样是基于ShutdownHook实现的。
AbstractConfig的static代码:
- static {
 - Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
 - public void run() {
 - if (logger.isInfoEnabled()) {
 - logger.info("Run shutdown hook now.");
 - }
 - ProtocolConfig.destroyAll();
 - }
 - }, "DubboShutdownHook"));
 - }
 
六、总结
只要我们的应用运行在linux平台上,所有的优雅关闭方案都是基于linux提供的信号机制提供的,JVM也是如此。
Java并没有为我们提供与之一一对应的api,而是给出了个ShutdownHook机制,也能达到类似的效果,缺点是我们无法得知JVM关闭的原因。
像dubbo、spring boot等成熟的开源框架,都实现了自动注册ShutdownHook的功能,从而避免使用者忘记调用优雅关闭api引发问题,降低框架的使用难度。
                分享名称:常见Java应用如何优雅关闭
                
                标题来源:http://www.csdahua.cn/qtweb/news35/51835.html
            
网站建设、网络推广公司-快上网,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 快上网