zoukankan      html  css  js  c++  java
  • ShutdownHook

    想象一下,如果你现在刚好在 word 上写需求文档,电脑突然重启。等待开机完成,你可能会发现写了一个小时文档没有保存,就这么没了。。。

    一个正在运行 Java 应用如果突然将其停止,影响不止数据丢失,还会造成其他影响。比如:

    • 请求丢失:内存队列中等待执行请求丢失
    • 数据丢失:处于内存缓存中数据未持久化到磁盘
    • 文件损坏:正在写的文件没有没有更新完成,导致文件损坏
    • 业务中断:处理一半的业务被强行中断,如支付成功了,却没有更新到数据库中
    • 服务未下线:上游服务依然往停止节点发送请求

    所以在关闭服务之前,我们需要先做好善后工作,比如保存数据,清理资源,下线服务,然后才退出应用。这种有计划平滑的关闭应用相对直接停止应用,就显得非常『优雅』。

    ps: 仔细品味,优雅停机这个词真好~

    ShutdownHook

    Java 语言提供一种 ShutdownHook(钩子)进制,当 JVM 接受到系统的关闭通知之后,调用 ShutdownHook 内的方法,用以完成清理操作,从而平滑的退出应用。

    ShutdownHook代码如下:

            Runtime.getRuntime().addShutdownHook(new Thread(() -> {
                System.out.println("关闭应用,释放资源");
            }));
    

    Runtime.getRuntime().addShutdownHook(Thread) 需要传入一个线程对象,后续动作将会在该异步线程内完成。除了主动关闭应用(使用 kill -15 指令),以下场景也将会触发 ShutdownHook :

    • 代码执行结束,JVM 正常退出
    • 应用代码中调用 System#exit 方法
    • 应用中发生 OOM 错误,导致 JVM 关闭
    • 终端中使用 Ctrl+C(非后台运行)

    目前很多开源框架都是基于这个机制实现优雅停机,比如 Dubbo,Spring 等。

    相关注意点

    ShutdownHook 代码实现起来相对简单,但是我们还是需要小心下面这些坑。

    Runtime.getRuntime().addShutdownHook(Thread) 可以被多次调用

    我们可以多次调用 Runtime.getRuntime().addShutdownHook(Thread) 方法,从而增加多个。但是需要注意的是,多个 ShutdownHook 之间并无任何顺序,Java 并不会按照加入顺序执行,反而将会并发执行。

    所以尽量在一个 ShutdownHook 完成所有操作。

    ShutdownHook 需要尽快执行结束

    不要在 ShutdownHook 执行需要被阻塞代码,如 I/0 读写,这样就会导致应用短时间不能被关闭。

     Runtime.getRuntime().addShutdownHook(new Thread(() -> {
               while (true){
                   System.out.println("关闭应用,释放资源");
               }
            }));
    

    上面代码中,我们使用 while(true) 模拟长时间阻塞这种极端情况,关闭该应用时,应用将会一直阻塞在 while 代码中,导致应用没办法被关闭。

    除了阻塞之外,还需要小心其他会让线程阻塞的行为,比如死锁。

    为了避免 ShutdownHook 线程被长时间阻塞,我们可以引入超时进制。如果等待一定时间之后,ShutdownHook 还未完成,由脚本直接调用 kill -9 强制退出或者 ShutdownHook 代码中引入超时进制。

    文章首发于studyidea.cn/shutdownHook

    欢迎关注我的公众号:程序通事,获得日常干货推送。如果您对我的专题内容感兴趣,也可以关注我的博客:studyidea.cn

    其他平台.png

  • 相关阅读:
    linux sysfs (2)
    微软——助您启动云的力量网络虚拟盛会
    Windows Azure入门教学系列 全面更新啦!
    与Advanced Telemetry创始人兼 CTO, Tom Naylor的访谈
    Windows Azure AppFabric概述
    Windows Azure Extra Small Instances Public Beta版本发布
    DataMarket 一月内容更新
    和Steve, Wade 一起学习如何使用Windows Azure Startup Tasks
    现实世界的Windows Azure:与eCraft的 Nicklas Andersson(CTO),Peter Löfgren(项目经理)以及Jörgen Westerling(CCO)的访谈
    正确使用Windows Azure 中的VM Role
  • 原文地址:https://www.cnblogs.com/goodAndyxublog/p/11658187.html
Copyright © 2011-2022 走看看