SpringBoot 优雅停止服务的几种方法 - 第309篇

news/2024/11/22 18:04:44/

 

相关历史文章(阅读本文之前,您可能需要先看下之前的系列👇

国内最全的Spring Boot系列之三

一分钟get:缓存穿透、缓存击穿、缓存雪崩 - 第304篇

布隆过滤器Bloom Filter竟然让我解决了一个大厂的问题 - 第305篇

100G的文件如何读取 - 第306篇

100G的文件如何读取续集 - 第307篇

Java语言的优雅停机 - 第308篇

 

师傅:对于java的shutdown hook有所了解之后,我们还是重点来看看Spring Boot如何优化停止服务吧。

悟纤:师傅,这节课那我认真听了,不然到时候生产环境都不知道如何正确停止服务了。

师傅:你这话… 说的… 师傅讲的每节课都很重要,好不。

悟纤:师傅,每节课我都有认真听的,不行待会你随便考我下。

师傅:那我们今天先把这个SpringBoot如何优雅停止学习完,在慢慢折磨你…

悟纤:师傅,我脑瓜怎么就嗡嗡的呐。

 

 

一、准备工作

1.1 准备一个项目

       随便创建一个Spring Boot项目,这里使用的是截止到2020年5月 最新的版本:2.2.7.RELEASE。

 

1.2 创建一个bean

       我们创建一个Bean ,有一个销毁的方法:

@Component
public class TerminateBean {@PreDestroypublic void preDestroy() {System.out.println("TerminalBean is destroyed");}}

       在接下来的测试中,主要是看这个preDestroy会不会被执行。

 

1.3 添加actuator的功能

       SpringBoot 提供的actuator的功能,它可以执行shutdown, health, info等,默认情况下,actuator的shutdown是disable的,我们需要打开它。

       利用actuator也是停止服务的方式,在下面会使用到,这里先把依赖添加进来。

引入acturator的maven依赖:

		<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency>

打开shutdown节点:

       修改applicatoin.properties文件:

management.endpoint.shutdown.enabled=true
management.endpoints.web.exposure.include=*

 

       这里暴露了所有的,也可以指定暴露shutdown:

management.endpoint.shutdown.enabled=true
management.endpoints.web.exposure.include=shutdown

 

二、SpringBoot的n中停机操作

2.1 Run As – Java Application运行 – Console Termiante关闭

       我们使用Run As – Java Application的方式进行运行我们的Application,启动成功之后,使用Console中的Terminate关闭。

此时控制台不会执行preDestroy方法。

 

2.2 Run As – Spring Boot App运行 – Console Terminate关闭

我们使用Run As – Spring Boot App的方式进行运行我们的Application,启动成功之后,使用Console中的Terminate关闭。

       此时控制台会执行preDestroy方法。

 

2.3 Run As – Java Application运行 – kill -15 pid关闭

       我们使用Run As – Java Application的方式进行运行我们的Application,启动成功之后,kill -15 pid。

       此时控制台会执行preDestroy方法。

2020-05-09 19:47:08.640  INFO 682 --- [extShutdownHook] o.s.s.concurrent.ThreadPoolTaskExecutor  : Shutting down ExecutorService 'applicationTaskExecutor'
TerminalBean is destroyed

 

       注意控制台的打印信息:有一个我们在前面讲过的非常熟悉的extShutdownHook,不然猜出Spring底层也是使用了

Runtime.getRuntime().addShutdownHook(Thread hook);

 

       我们看下源码:

org.springframework.context.support.AbstractApplicationContext.registerShutdownHook()

@Overridepublic void registerShutdownHook() {if (this.shutdownHook == null) {// No shutdown hook registered yet.this.shutdownHook = new Thread() {@Overridepublic void run() {synchronized (startupShutdownMonitor) {doClose();}}};Runtime.getRuntime().addShutdownHook(this.shutdownHook);}}

 

2.4 Run As – Java Application运行 – kill -9 pid关闭

       我们使用Run As – Java Application的方式进行运行我们的Application,启动成功之后,kill -9 pid。

       此时控制台不会执行preDestroy方法。

 

2.5 actuator:post shutdown

       还记得我们在准备工作的时候,添加了actuator,这个会暴露出来一个/actuator/shutdown的地址,我们就可以请求一下:

curl -X POST  http://localhost:8080/actuator/shutdown

 

注意:是post方法,而且post这里要大写、大写、大写,重要的事情说3遍,否则会报错:

{"timestamp": "2020-05-11T07:37:55.154+0000","status": 405,"error": "Method Not Allowed","message": "Request method 'post' not supported","path": "/actuator/shutdown"
}

 

请求成功的话,会返回:

{"message":"Shutting down, bye..."}

 

       此时控制台会执行preDestroy方法。

 

2.6 ApplicationContext.close()

       这种方式的思路就是获取到ApplicationContext,然后调用它的close()方法。

@RestController
public class ShutDownController implements ApplicationContextAware {private ApplicationContext applicationContext;@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {this.applicationContext = applicationContext;}@RequestMapping("/shutdownByCTX")public String shutdownByCTX(){ConfigurableApplicationContext ctx = (ConfigurableApplicationContext) applicationContext;ctx.close();return "context is shutdown!!!";}}

 

说明:编写一个类实现ApplicationContextAware,主要是要获取上下文ApplicationContext;然后我们暴露一个请求/shutdownByCTX,在此方法使用applicationContext的close方法。

       测试,可以通过浏览器访问地址:

http://127.0.0.1:8080/shutdownByCTX

 

注意:当请求/shutdownByCTX的话,并不能看到返回值,而是:

curl: (52) Empty reply from server

              此时控制台会执行preDestroy方法。

 

2.7 SpringApplication.exit()

       利用SpringApplication提供的exit方法:

	@RequestMapping("/shutdownBySpringApplication")public String shutdownBySpringApplication(){SpringApplication.exit(applicationContext,(ExitCodeGenerator)()->0);return "context is shutdown!!!";}

 

此时控制台会执行preDestroy方法。

 

 

2.8 pid | xargs kill

       此方式是将pid写入到文件,然后使用xargs kill进行关闭服务。

	public static void main(String[] args) {SpringApplication application = new SpringApplication(SpringBootShutdownDemoApplication.class);// 指定一个文件,写入pid号application.addListeners(new ApplicationPidFileWriter("/data/tmp/app.pid"));application.run(args);}

 

       通过命令 cat /data/tmp/app.pid | xargs kill 命令直接停止服务。

此时控制台会执行preDestroy方法。

 

三、悟纤小结

悟纤:师傅,你今天这节课讲的有点乱呐?是不是来事了?

 

师傅:徒儿,看来你今天没有挨抽,不舒服,是吧?

 

悟纤:师傅,那怪徒儿太笨,没消化的了嘛。

 

师傅:那好,你按照自己的理解,来和大家梳理下。

 

 

小结下:

一、通过应用暴露shutdown

(1)actutor的/actutor/shutdown方法(需要配置):此时控制台会执行preDestroy方法。

(2)利用Application的close()方法(需要编码暴露出一个访问的方法):此时控制台会执行preDestroy方法。

(3)利用SpingApplication的exit()方法(需要编码暴露出一个访问的方法):此时控制台会执行preDestroy方法。

 

二、kill

(1)kill -9 pid:不需要编码,也不需要配置,利用操作系统的强制关闭经常指令;此时控制台不会执行preDestroy方法。

(2)kill -15 pid:不需要编码,也不需要配置,利用操作系统的强制关闭经常指令;此时控制台会执行preDestroy方法。

(3)kill | xargs kill:需要编码,然后利用操作系统的指令cat /data/tmp/app.pid | xargs kill;此时控制台会执行preDestroy方法。

 

四、生产环境怎么玩呐?

       在生产环境,我们是这么玩的?

编写一个sh脚本,通过grep查找到我们项目的pid,然后先使用kill -15 pid,然后sleep一下,然后在超找pid , 如果没找到,说明已经关闭了,如果找到了,说明关闭失败了,那么就使用kill -9 pid强制关闭进程了。

 

我就是我,是颜色不一样的烟火。
我就是我,是与众不同的小苹果。

学院中有Spring Boot相关的课程:

à悟空学院:https://t.cn/Rg3fKJD

SpringBoot视频:http://t.cn/A6ZagYTi

Spring Cloud视频:http://t.cn/A6ZagxSR

SpringBoot Shiro视频:http://t.cn/A6Zag7IV

SpringBoot交流平台:https://t.cn/R3QDhU0

SpringData和JPA视频:http://t.cn/A6Zad1OH

SpringSecurity5.0视频:http://t.cn/A6ZadMBe

Sharding-JDBC分库分表实战:http://t.cn/A6ZarrqS

分布式事务解决方案「手写代码」:http://t.cn/A6ZaBnIr

JVM内存模型和性能调优:http://t.cn/A6wWMVqG

 


http://www.ppmy.cn/news/696761.html

相关文章

x264编码指南——码率控制

x264是一个 H.264/MPEG4 AVC 编码器&#xff0c;本指南将指导新手如何创建高质量的H.264视频。 对于普通用户通常有两种码率控制模式&#xff1a;crf&#xff08;Constant Rate Factor)和Two pass ABR。码率控制是一种决定为每一个视频帧分配多少比特数的方法&#xff0c;它将决…

苹果电脑(mac os x)键盘使用技巧

苹果电脑&#xff08;mac os x)键盘使用技巧 启动电脑时的巧妙使用&#xff1a; 1、在电脑启动时&#xff0c;同时按住“option”键可以重建桌面&#xff0c;此操作应每月做一次。 2、在电脑启动时&#xff0c;按住“shift”键可以关闭所有系统功能扩展。 3、在电脑启动时&…

几种典型的颜色空间

二&#xff0e;几种典型的颜色空间 &#xff08;一&#xff09;CIE色度模型 国际照明委员会&#xff08;CIE&#xff0c;Commission Internationale de LEclairage / International Commission on Illumination&#xff09;的色度模型是最早使用的模型之一。它是三维模型&am…

geoserver发布arcgis server离线瓦片

1.使用tif文件也可以发布服务&#xff0c;但是我下载的tif文件发布的服务总数模糊不清&#xff0c;原因可能是地图比例尺问题。 2.仔细研究&#xff0c;发现下载的arcgis server瓦片都是高清的&#xff0c;于是想到直接加载arcgis瓦片&#xff0c;这样图片/坐标系之间问题都完…

力扣方法总结-----动态规划

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 一、动态规划二、动态规划五部曲1.确定DP数组的含义2.确定递推公式3.确定初始值4.确定遍历顺序5.举例推导DP数组&#xff0c;打印程序中DP数组日志 三、例子 一、动…

The Unarchiver Unzip RAR ZIP for mac(解压缩软件)

Unarchiver-Unzip RAR ZIP Mac版是一个非常易于使用的应用程序&#xff0c;可让您解压缩数十种存档格式。例如&#xff1a;Rar&#xff0c;Zip&#xff0c;7z&#xff0c;Tar&#xff0c;Xz&#xff0c;Iso&#xff0c;Lha&#xff0c;bz2&#xff0c;Lzh&#xff0c;cab&#…

Imagine-快速的图片压缩工具

概述 Imagine是一款桌面应用程序&#xff0c;用于通过现代友好的UI压缩PNG和JPEG&#xff0c;为web保存 安装 对于Windows&#xff0c;macOS和Linux&#xff0c;请从以下位置下载二进制文件&#xff1a;[download href”https://github.com/meowtec/Imagine" target”b…

python解压缩-[rar]、[zip]

Python版本&#xff1a;3.9.6 ide&#xff1a;PyCharm 2021.1.3 常用的压缩格式有很多种&#xff0c;而不同的压缩包的解压需要用到不同的库&#xff0c;下面根据一些常用的压缩包给出各自的解决方案。 目录 rar格式 zip格式 完整源码 rar格式 主要代码就两行&#xff0c;如…