欢迎访问欧博开户!

首页科技正文

潍坊赶集网:Java 若何实现优雅停服?刨根问底

admin2020-05-2054

在 Java 的天下里遨游,若是能拥有一双善于发现的眼睛,有许多器械留心去看,外加耐心助力,仔细去品,往往会品出不一样的味道。

通过本次分享,能让你轻松 get 如下几点,绝对收获满满。

a)若何让 Java 程序实现优雅停服?有头脑才是硬道理!

b)addShutdownHook 的使用场景?会用才是王道!

c)addShutdownHook 钩子函数到底是个啥?刨根问底!

1. 若何让 Java 程序实现优雅停服?

无论是自研基础服务框架,照样剖析开源项目源码,仔细的 Java 开发同砚,都市发现 Runtime.getRuntime().addShutdownHook 这么一句代码的身影,这句到底是干什么用的?

接下来就一起细品,看看它香不香?

阿里开源的数据同步神器 Canal 启动时的部门源码:

Apache 麾下的用于海量日志网络的 Flume 启动时的部门源码:

 

瞻仰了一下开源的项目,不妨从中提炼一下共性(同样的代码遇到多次,势必会品出味道),写段代码跑跑看(站在 flume 源码的肩膀上,腾飞)。

 1 import java.util.concurrent.ScheduledThreadPoolExecutor;
 2 import java.util.concurrent.TimeUnit;
 3 
 4 /**
 5  * 体验 Java 优雅停服
 6  *
 7  * @author 一猿小讲
 8  */
 9 public class Application {
10 
11     /**
12      * 监控服务
13      */
14     private ScheduledThreadPoolExecutor monitorService;
15 
16     public Application() {
17         monitorService = new ScheduledThreadPoolExecutor(1);
18     }
19 
20     /**
21      * 启动监控服务,监控一下内存信息
22      */
23     public void start() {
24         System.out.println(String.format("启动监控服务 %s", Thread.currentThread().getId()));
25         monitorService.scheduleWithFixedDelay(new Runnable() {
26             @Override
27             public void run() {
28                 System.out.println(String.format("最大内存: %dm  已分配内存: %dm  已分配内存中的剩余空间: %dm  最大可用内存: %dm",
29                         Runtime.getRuntime().maxMemory() / 1024 / 1024,
30                         Runtime.getRuntime().totalMemory() / 1024 / 1024,
31                         Runtime.getRuntime().freeMemory() / 1024 / 1024,
32                         (Runtime.getRuntime().maxMemory() - Runtime.getRuntime().totalMemory() +
33                                 Runtime.getRuntime().freeMemory()) / 1024 / 1024));
34             }
35         }, 2, 2, TimeUnit.SECONDS);
36     }
37 
38     /**
39      * 释放资源(代码来源于 flume 源码)
40      * 主要用于关闭线程池(看不懂的同砚莫纠结,当做黑盒去看待)
41      */
42     public void stop() {
43         System.out.println(String.format("最先关闭线程池 %s", Thread.currentThread().getId()));
44         if (monitorService != null) {
45             monitorService.shutdown();
46             try {
47                 monitorService.awaitTermination(10, TimeUnit.SECONDS);
48             } catch (InterruptedException e) {
49                 System.err.println("Interrupted while waiting for monitor service to stop");
50             }
51             if (!monitorService.isTerminated()) {
52                 monitorService.shutdownNow();
53                 try {
54                     while (!monitorService.isTerminated()) {
55                         monitorService.awaitTermination(10, TimeUnit.SECONDS);
56                     }
57                 } catch (InterruptedException e) {
58                     System.err.println("Interrupted while waiting for monitor service to stop");
59                 }
60             }
61         }
62         System.out.println(String.format("线程池关闭完成 %s", Thread.currentThread().getId()));
63     }
64 
65     /**
66      * 应用入口
67      */
68     public static void main(String[] args) {
69         Application application = new Application();
70         // 启动服务(每隔一段时间监控输出一下内存信息)
71         application.start();
72 
73         // 添加钩子,实现优雅停服(主要验证钩子的作用)
74         final Application appReference = application;
75         Runtime.getRuntime().addShutdownHook(new Thread("shutdown-hook") {
76             @Override
77             public void run() {
78                 System.out.println("接收到退出的讯号,最先扫除战场,释放资源,完成优雅停服");
79                 appReference.stop();
80             }
81         });
82         System.out.println("服务启动完成");
83     }
84 }

经常读文的我很清晰,耐心读文章中源码的同砚应该很少,以是我照样用图给你简朴捋一捋。

标注1:start 方式行使线程池启动一个线程去准时监控内存信息;

标注2:stop 方式用于在退出程序之前,举行关闭线程池进而释放资源。

程序跑起来,效果如下。

潍坊赶集网:Java 若何实现优雅停服?刨根问底 第1张

 

当举行 kill 操作时,程序确实举行了资源释放,效果确实很优雅。

潍坊赶集网:Java 若何实现优雅停服?刨根问底 第2张

 

一切看似那么自然,一切又是那么完善,这是真的吗?杀历程时刻若是用 kill -9,这种情况下会发生什么征象呢?

潍坊赶集网:Java 若何实现优雅停服?刨根问底 第3张

 

呜呼!效果不会骗人的,当用 kill -9 的时刻,就显得很粗暴了,压根不管什么资源释放,不管三七二十一,就是终止程序。

估量许多同砚,都善于用 kill -9 举行杀历程,为了线上的应用平安,照样用 kill -15 下令杀历程吧,这样会给应用留点时间去扫除一下战场,释放一下资源。

好了,通过仔细品味,借助 JDK 自带的 addShutdownHook 来助力应用,确实能让线上服务跑起来很优雅。

有头脑才是硬道理!

2. addShutdownHook 的使用场景?

通过代码试验,能够感知 addShutdownHook(new Thread(){}) 是 JVM 销毁前要执行的一个线程,那么只要是涉及到资源接纳的场景,应该都可以知足,下面简朴枚举几个。

a)数据同步神器 Canal 借助它,来举行关闭 socket 链接、释放 canal 的事情节点、清算缓存信息等;

b)海量日志网络 Flume 借助它,来实现线程池资源关闭、事情线程住手等;

c)在应用正常退出时,执行特定的营业逻辑、关闭资源等操作。

d)在 OOM 宕机、 CTRL+C、或执行 kill pid,导致 JVM 非正常退出时,加入需要的拯救措施成为可能。

实在,在 Java 的天下里遨游,只有想不到的,没有做不到的!

3. addShutdownHook 钩子函数是个啥?

刨根还要问到底!

潍坊赶集网:Java 若何实现优雅停服?刨根问底 第4张

 

Hook 翻译过来是「钩子」的意思,那顾名思义就是用来挂器械的。

潍坊赶集网:Java 若何实现优雅停服?刨根问底 第5张

 

如图所示,在现实生涯中,要制作腊肉,首先用钩子把肉勾住,然后挂在竹竿上,这应该是钩子的作用。

生涯云云,一切设计理念都源于生涯,在 Java 的天下里,亦是云云。

潍坊赶集网:Java 若何实现优雅停服?刨根问底 第6张

 

如上图 Runtime 的源码所示,遵照 Java 的焦点头脑「一切皆是工具」,那么可以把 addShutdownHook 方式可以视作挂钩子,实在称之为钩子函数会好一些,而现实生涯中的肉就可以抽象为释放资源的线程。

只要有这个钩子函数,对外就提供了扩展能力,研发职员就可以往钩子上挂种种自定义的场景实现,这种设计你细品那绝对是香!这也就是 Canal、Flume、Tomcat 等差别应用,在优雅停服时有着差别的实现的缘故原由吧。

大白话,钩子函数有了,想挂什么器械,凭据心情自己定就好了。

再深入去刨会发现,由于底层数据结构接纳 Map 来举行存储,那么就支持研发职员挂多个 shutdownHook 的实现,又带来了无限的可能性(又带来了无限的「刺激」,自己好好去体会)。

潍坊赶集网:Java 若何实现优雅停服?刨根问底 第7张

 

好了,制止头大,就刨到这儿吧,感兴趣的可自行顺着思绪继续刨下去。

4. 寄语,写在最后

作为研发职员:要拥有一双善于发现的眼睛,要善于发现代码之美。

作为研发职员:要时常思索面临当前的项目,是否能够简朴重构让程序跑的更顺溜。

作为研发职员:要多看、多悟、多提炼、多实践。

作为研发职员:请不要放弃代码,由于程序终会铸就人生。

本次分享就到这里,希望对你有所辅助吧。一起聊手艺、谈营业、喷架构,少走弯路,不踩大坑。

会连续输出原创精彩分享,敬请期待!关注同名民众号:一猿小讲,回复「1024」可以获取经心为您准备的职场打怪进阶资料。

,

阳光在线

阳光在线www.sssmobilesss.com(原诚信在线)现已开放阳光在线手机版下载。阳光在线游戏公平、公开、公正,用实力赢取信誉。

转载声明:本站发布文章及版权归原作者所有,转载本站文章请注明文章来自欧博开户!

本文链接:http://www.wednesdayjf.com/post/1154.html

网友评论

最新评论

  • AllbetGmaing官网 10/21 说:

    Allbet代理欢迎进入Allbet代理(Allbet Game):www.aLLbetgame.us,欧博官网是欧博集团的官方网站。欧博官网开放Allbet注册、Allbe代理、Allbet电脑客户端、Allbet手机版下载等业务。一定一定要看这个!

  • AllbetGmaing官网 10/21 说:

    Allbet代理欢迎进入Allbet代理(Allbet Game):www.aLLbetgame.us,欧博官网是欧博集团的官方网站。欧博官网开放Allbet注册、Allbe代理、Allbet电脑客户端、Allbet手机版下载等业务。一定一定要看这个!

  • 欧博APP下载 10/21 说:

    环球UG欢迎进入环球UG官网(UG环球):www.ugbet.us,环球UG官方网站:www.ugbet.net开放环球UG网址访问、环球UG会员注册、环球UG代理申请、环球UG电脑客户端、环球UG手机版下载等业务。继续更吗

  • 欧博亚洲网址 10/21 说:

    欧博官网手机欢迎进入欧博官网手机(Allbet Game):www.aLLbetgame.us,欧博官网是欧博集团的官方网站。欧博官网开放Allbet注册、Allbe代理、Allbet电脑客户端、Allbet手机版下载等业务。看得心动

  • 欧博官网手机 10/20 说:

    联博统计www.326681.com采用以太坊区块链高度哈希值作为统计数据,联博以太坊统计数据开源、公平、无任何作弊可能性。联博统计免费提供API接口,支持多语言接入。任谁都喜欢

  • UG环球会员充值 10/20 说:

    欧博亚洲客户端欢迎进入欧博亚洲客户端(Allbet Game):www.aLLbetgame.us,欧博官网是欧博集团的官方网站。欧博官网开放Allbet注册、Allbe代理、Allbet电脑客户端、Allbet手机版下载等业务。每日一逛

  • 欧博allbet网址 10/19 说:

    联博开奖www.326681.com采用以太坊区块链高度哈希值作为统计数据,联博以太坊统计数据开源、公平、无任何作弊可能性。联博统计免费提供API接口,支持多语言接入。夸夸你~

  • 环球UG网址 10/19 说:

    ALLBET官网娱乐平台开户欢迎进入ALLBET官网娱乐平台开户:www.aLLbetgame.us,欧博官网是欧博集团的官方网站。欧博官网开放Allbet注册、Allbe代理、Allbet电脑客户端、Allbet手机版下载等业务。夸夸这个网站