最后
由于文案过于长,在此就不一一介绍了,这份Java后端架构进阶笔记内容包括:Java集合,JVM、Java并发、微服务、SpringNetty与 RPC 、网络、日志 、Zookeeper 、Kafka 、RabbitMQ 、Hbase 、MongoDB、Cassandra 、Java基础、负载均衡、数据库、一致性算法、Java算法、数据结构、分布式缓存等等知识详解。
本知识体系适合于所有Java程序员学习,关于以上目录中的知识点都有详细的讲解及介绍,掌握该知识点的所有内容对你会有一个质的提升,其中也总结了很多面试过程中遇到的题目以及有对应的视频解析总结。
那么,"优雅"怎么理解呢?
先说什么情况我们认为不优雅:
1、服务停止时,没有关闭对应的监控,导致应用停止后发生大量报警。
2、应用停止时,没有通知外部调用方,很多请求还会过来,导致很多调用失败。
3、应用停止时,有线程正在执行中,执行了一半,JVM进程就被干掉了。
4、应用启动时,服务还没准备好,就开始对外提供服务,导致很多失败调用。
5、应用启动时,没有检查应用的健康状态,就开始对外提供服务,导致很多失败调用。
以上,都是我们认为的不优雅的情况,那么,反过来,优雅上下线就是一种避免上述情况发生的手段。
一个应用的优雅上下线涉及到的内容其实有很多,从底层的操作系统、容器层面,到编程语言、框架层面,再到应用架构层面,涉及到的知识很广泛。
其实,优雅上下线中,最重要的还是优雅下线。因为如果下线过程不优雅的话,就会发生很多调用失败了、服务找不到等问题。所以很多时候,大家也会提优雅停机这样的概念。
本文后面介绍的优雅上下线也重点关注优雅停机的过程。
操作系统&容器的优雅上下线
关于操作系统,我之前有一篇文章专门介绍过这个话题,可能大家没有注意到,那时候介绍的主题是为什么不能在线上机器中随便执行kill -9。
其实,这背后的思考就是优雅上下线。
我们知道,kill -9之所以不建议使用,是因为kill -9特别强硬,系统会发出SIGKILL信号,他要求接收到该信号的程序应该立即结束运行,不能被阻塞或者忽略。
这个过程显然是不优雅的,因为应用立刻停止的话,就没办法做收尾动作。而更优雅的方式是kill -15。
当使用kill -15时,系统会发送一个SIGTERM的信号给对应的程序。当程序接收到该信号后,具体要如何处理是自己可以决定的。
kill -15会通知到应用程序,这就是操作系统对于优雅上下线的最基本的支持。
以前,在操作系统之上就是应用程序了,但是,自从容器化技术推出之后,在操作系统和应用程序之间,多了一个容器层,而Docker、k8s等容器其实也是支持优雅上下线的。
如Docker中同样提供了两个命令, docker stop 和 docker kill
docker stop就像kill -15一样,他会向容器内的进程发送SIGTERM信号,在10S之后(可通过参数指定)再发送SIGKILL信号。
而docker kill就像kill -9,直接发送SIGKILL信号。
JVM的优雅上下线
在操作系统、容器等对优雅上下线有了基本的支持之后,在接收到docker stop、kill -15等命令后,会通知应用进程进行进程关闭。
而Java应用在运行时就是一个独立运行的进程,这个进程是如何关闭的呢?
Java程序的终止运行是基于JVM的关闭实现的,JVM关闭方式分为正常关闭、强制关闭和异常关闭3种。
这其中,正常关闭就是支持优雅上下线的。正常关闭过程中,JVM可以做一些清理动作,比如删除临时文件。
当然,开发者也是可以自定义做一些额外的事情的,比如通知应用框架优雅上下线操作。
而这种机制是通过JDK中提供的shutdown hook实现的。JDK提供了Java.Runtime.addShutdownHook(Thread hook)方法,可以注册一个JVM关闭的钩子。
例子如下:
package com.hollis;
public class ShutdownHookTest {
public static void main(String[] args) {
boolean flag = true;
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
System.out.println(“hook execute…”);
}));
while (flag) {
// app is runing
}
System.out.println(“main thread execute end…”);
}
}
执行命令:
jps
6520 ShutdownHookTest
6521 Jps
kill 6520
控制台输出内容:
hook execute…
Process finished with exit code 143 (interrupted by signal 15: SIGTERM)
可以看到,当我们使用kill(默认kill -15)关闭进程的时候,程序会先执行我注册的shutdownHook,然后再退出,并且会给出一个提示:interrupted by signal 15: SIGTERM
Spring的优雅上下线
有了JVM提供的shutdown hook之后,很多框架都可以通过这个机制来做优雅下线的支持。
比如Spring,他就会向JVM注册一个shutdown hook,在接收到关闭通知的时候,进行bean的销毁,容器的销毁处理等操作。
同时,作为一个成熟的框架,Spring也提供了事件机制,可以借助这个机制实现更多的优雅上下线功能。
ApplicationListener是Spring事件机制的一部分,与抽象类ApplicationEvent类配合来完成ApplicationContext的事件机制。
开发者可以实现ApplicationListener接口,监听到 Spring 容器的关闭事件(ContextClosedEvent),来做一些特殊的处理:
@Component
public class MyListener implements ApplicationListener {
@Override
public void onApplicationEvent(ContextClosedEvent event) {
最后
光给面试题不给答案不是我的风格。这里面的面试题也只是凤毛麟角,还有答案的话会极大的增加文章的篇幅,减少文章的可读性
Java面试宝典2021版
最常见Java面试题解析(2021最新版)
2021企业Java面试题精选
项目源码】](https://bbs.youkuaiyun.com/forums/4f45ff00ff254613a03fab5e56a57acb)收录**