ITPub博客

首页 > 应用开发 > > 常见Java应用如何优雅关闭

常见Java应用如何优雅关闭

作者:supergirlxu 时间:2019-10-17 10:19:59 0 删除 编辑

作者:卢利如

来源:点我达技术

http://tech.dianwoda.com

一、前言

在我们进行系统升级的时候,往往需要关闭我们的应用,然后重启。在关闭应用前,我们希望做一些前置操作,比如关闭数据库、redis连接,清理zookeeper的临时节点,释放分布式锁,持久化缓存数据等等。

二、Linux的信号机制

在linux上,我们关闭进程主要是使用kill <pid>的方式。

当执行该命令以后,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线程。

四、Spring Boot提供的优雅关闭功能

我们一般采用如下的方式,启动一个Spring boot应用:

public static void main(String[] args) throws Exception {

SpringApplication.run(SampleController.class, args);

}

SpringApplication.run()代码如下,会调用到refreshContext(context)方法:

很明显,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引发问题,降低框架的使用难度。

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/644/viewspace-3139592/ ,如需转载,请注明出处,否则将追究法律责任。

上一篇: jQuery
请登录后发表评论 登录
全部评论

注册时间:2019-04-12

  • 博文量
    220
  • 访问量
    1690