在使用 SpringBoot 的时候,都要涉及到服务的停止和启动,当我们停止服务的时候,很多时候大家都是kill -9 直接把程序进程杀掉,这样程序不会执行优雅的关闭。而且一些没有执行完的程序就会直接退出。

我们很多时候都需要安全的将服务停止,也就是把没有处理完的工作继续处理完成。比如停止一些依赖的服务,输出一些日志,发一些信号给其他的应用系统,这个在保证系统的高可用是非常有必要的。那么咱么就来看一下几种停止 SpringBoot 的方法。

第一种就是 SpringBoot 提供的actuator的功能,它可以执行shutdown, health, info等,默认情况下,actuator的shutdown是disable的,我们需要打开它。首先引入acturator的maven依赖。

org.springframework.boot

spring-boot-starter-actuator

然后将shutdown节点打开,也将/actuator/shutdown暴露web访问也设置上,除了shutdown之外还有health, info的web访问都打开的话将management.endpoints.web.exposure.include=*就可以。将如下配置设置到application.properties里边。设置一下服务的端口号为3333。整编:微信公众号,搜云库技术团队,ID:souyunku

server.port=3333

management.endpoint.shutdown.enabled=true

management.endpoints.web.exposure.include=shutdown

接下来,咱们创建一个SpringBoot工程,然后设置一个bean对象,配置上PreDestroy方法。这样在停止的时候会打印语句。bean的整个生命周期分为创建、初始化、销毁,当最后关闭的时候会执行销毁操作。在销毁的方法中执行一条输出日志。

package com.hqs.springboot.shutdowndemo.bean;

import javax.annotation.PreDestroy;

public class TerminateBean {

@PreDestroy

public void preDestroy() {

System.out.println("TerminalBean is destroyed");

}

}

做一个configuration,然后提供一个获取bean的方法,这样该bean对象会被初始化。

package com.hqs.springboot.shutdowndemo.config;

import com.hqs.springboot.shutdowndemo.bean.TerminateBean;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

@Configuration

public class ShutDownConfig {

@Bean

public TerminateBean getTerminateBean() {

return new TerminateBean();

}

}

在启动类里边输出一个启动日志,当工程启动的时候,会看到启动的输出,接下来咱们执行停止命令。

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

以下日志可以输出启动时的日志打印和停止时的日志打印,同时程序已经停止。是不是比较神奇。

第二种方法也比较简单,获取程序启动时候的context,然后关闭主程序启动时的context。这样程序在关闭的时候也会调用PreDestroy注解。如下方法在程序启动十秒后进行关闭。

/* method 2: use ctx.close to shutdown all application context */

ConfigurableApplicationContext ctx = SpringApplication.run(ShutdowndemoApplication.class, args);

try {

TimeUnit.SECONDS.sleep(10);

} catch (InterruptedException e) {

e.printStackTrace();

}

ctx.close();

第三种方法,在SpringBoot启动的时候将进程号写入一个app.pid文件,生成的路径是可以指定的,可以通过命令 cat /Users/huangqingshi/app.id | xargs kill 命令直接停止服务,这个时候bean对象的PreDestroy方法也会调用的。这种方法大家使用的比较普遍。写一个start.sh用于启动springboot程序,然后写一个停止程序将服务停止。  

/* method 3 : generate a pid in a specified path, while use command to shutdown pid :

'cat /Users/huangqingshi/app.pid | xargs kill' */

SpringApplication application = new SpringApplication(ShutdowndemoApplication.class);

application.addListeners(new ApplicationPidFileWriter("/Users/huangqingshi/app.pid"));

application.run();

第四种方法,通过调用一个SpringApplication.exit()方法也可以退出程序,同时将生成一个退出码,这个退出码可以传递给所有的context。这个就是一个JVM的钩子,通过调用这个方法的话会把所有PreDestroy的方法执行并停止,并且传递给具体的退出码给所有Context。通过调用System.exit(exitCode)可以将这个错误码也传给JVM。程序执行完后最后会输出:Process finished with exit code 0,给JVM一个SIGNAL。整编:微信公众号,搜云库技术团队,ID:souyunku

/* method 4: exit this application using static method */

ConfigurableApplicationContext ctx = SpringApplication.run(ShutdowndemoApplication.class, args);

exitApplication(ctx);

public static void exitApplication(ConfigurableApplicationContext context) {

int exitCode = SpringApplication.exit(context, (ExitCodeGenerator) () -> 0);

System.exit(exitCode);

}

第五种方法,自己写一个Controller,然后将自己写好的Controller获取到程序的context,然后调用自己配置的Controller方法退出程序。通过调用自己写的/shutDownContext方法关闭程序:curl -X POST http://localhost:3333/shutDownContext。

package com.hqs.springboot.shutdowndemo.controller;

import org.springframework.beans.BeansException;

import org.springframework.context.ApplicationContext;

import org.springframework.context.ApplicationContextAware;

import org.springframework.context.ConfigurableApplicationContext;

import org.springframework.web.bind.annotation.GetMapping;

import org.springframework.web.bind.annotation.PostMapping;

import org.springframework.web.bind.annotation.RestController;

@RestController

public class ShutDownController implements ApplicationContextAware {

private ApplicationContext context;

@PostMapping("/shutDownContext")

public String shutDownContext() {

ConfigurableApplicationContext ctx = (ConfigurableApplicationContext) context;

ctx.close();

return "context is shutdown";

}

@GetMapping("/")

public String getIndex() {

return "OK";

}

@Override

public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {

context = applicationContext;

}

}

好了,SpringBoot的优雅关闭方法也都实现好了,也有同学问,如何暴力停止呢,简单,直接kill -9 相应的PID即可

总结一下:

以上这几种方法实现的话比较简单,但是真实工作中还需要考虑的点还很多,比如需要保护暴露的点不被别人利用,一般要加一些防火墙,或者只在内网使用,保证程序安全。整编:微信公众号,搜云库技术团队,ID:souyunku

在真实的工作中的时候第三种比较常用,程序中一般使用内存队列或线程池的时候最好要优雅的关机,将内存队列没有处理的保存起来或线程池中没处理完的程序处理完。但是因为停机的时候比较快,所以停服务的时候最好不要处理大量的数据操作,这样会影响程序停止。

好了,大家觉得还没看全的话,可以访问我的GIT代码:

https://github.com/stonehqs/shutdowndemo.git

往期推荐

双11开始了,1核2G,1年62元,3年200元,限量秒杀

华为开源 JDK,高性能、发行版、太牛逼啦!

这 IDEA 超全优化设置,提升,效率,属实牛逼!

SpringBoot 整合 Quartz 实现 Java 定时任务的动态配置

阅读原文: 最新 3625页大厂面试题

netlogon启动后停止_优雅停止 SpringBoot 服务,拒绝 kill 9 暴力停止!相关推荐

  1. python 程序停止打印日志_优雅停止 SpringBoot 服务,拒绝 kill -9 暴力停止!

    在使用 SpringBoot 的时候,都要涉及到服务的停止和启动,当我们停止服务的时候,很多时候大家都是kill -9 直接把程序进程杀掉,这样程序不会执行优雅的关闭.而且一些没有执行完的程序就会直接 ...

  2. 如果优雅停止 SpringBoot 服务,应该拒绝 kill -9 暴力停止

    搞IT 在使用 SpringBoot 的时候,都要涉及到服务的停止和启动,当我们停止服务的时候,很多时候大家都是kill -9 直接把程序进程杀掉,这样程序不会执行优雅的关闭.而且一些没有执行完的程序 ...

  3. AndroidStudio_安卓原生开发_获取系统S/N序列号_实现在springboot服务端_设备远程保活监控---Android原生开发工作笔记159

    android项目做好了,以后,所有pad设备,在springboot服务后端,需要实现监控,那么,这个时候就需要保活机制,这个保活机制,可以让服务端,实时监控,所有的pad设备的,工作状态. 实现思 ...

  4. netlogon启动后停止_自耦变压器降压启动原理

    变压器起动方式有哪些 1.已运行变压器停下后再启动时,直接空载启动(低压侧负荷先断开):小型变压器一般采用直接启动. 2.新安装的630KVA以上容量宜采用先空载充电三次,检查无异常后再正常投运:超高 ...

  5. netlogon启动后停止_【漏洞通报】微软NetLogon提权漏洞

    近日,奇安信CERT监测到国外安全厂商发布了NetLogon 权限提升漏洞(CVE-2020-1472)的详细技术分析文章和验证脚本.此漏洞是微软8月份发布安全公告披露的紧急漏洞,CVSS漏洞评分10 ...

  6. netlogon启动后停止_【通告更新】漏洞EXP已流出,影响巨大,微软NetLogon权限提升漏洞安全风险通告第三次更新...

    近日,奇安信CERT监测到国外安全厂商发布了NetLogon 权限提升漏洞(CVE-2020-1472)的详细技术分析文章和验证脚本.此漏洞是微软8月份发布安全公告披露的紧急漏洞,CVSS漏洞评分10 ...

  7. network setup service启动后自动停止_一个简单的测试环境下的自动化部署方案

    笔者是公司是一个分前后端开发的公司.而笔者是一个普通的后端开发工程师.在和前端工程师协同开发时,为了给前端工程师提供接口,往往要将写好的代码交付并部署到测试环境.因而这导致笔者经常需要打包项目更新到测 ...

  8. application terminated怎么解决_优雅解决 SpringBoot 工程中多环境下 application.properties 的维护问题...

    个人微信号:geekoftaste, 期待与大家一起探讨! 背景 我们知道 SpringBoot 有一个全局的配置文件 application.properties, 可以把工程里用到的占位符,第三方 ...

  9. win10诊断启动后联网_小技巧:win10网络共享文件夹出现错误无法访问如何解决?...

    win10系统共享文件夹时在资源管理器中的网络里能够看到所共享的文件夹,但在打开文件夹时却出现 Windows无法访问 \\Desktop-r8ceh55\新建文件夹 请检查名称的拼写.否则,网络可能 ...

  10. 7034mysql意外停止_中国名创解决mysql数据库意外自动关闭(停止)的问题

    如果一个服务器上的网站永远都只有一个用户在访问,mysql还会自动关闭吗?我认为不会,这一个用户任他随意折腾(恶意攻击除外)想来mysql也不会自动关闭.如此说来那么mysql关闭的原因肯定就是程序给 ...

最新文章

  1. 在“内卷”、“红海”的2020 年,开垦计算机视觉领域的知识荒原:BatchNorm
  2. Java枚举原来还能这么用
  3. 汇编语言随笔(7)-访问内存的寻址方式和实验7(不同寻址方式的使用)
  4. Raspberry Pi 4B 安装 PyTorch
  5. windwos-sshfs
  6. python在abaqus中的应用代码下载_Python-(source-code)-in--Abaqus Python语言在Abaqus中的应用(源码) - 下载 - 搜珍网...
  7. 探索MySql.Data.dll
  8. 【C++】 C++标准模板库(一) Vector
  9. dj电商-数据表的设计-购物车表与订单表设计
  10. android activty动画,Activity动画效果
  11. 如何将零填充到字符串?
  12. win7 开启梦幻桌面
  13. 小区停车管理系统(SQL,JDBC)
  14. 计算机专业保研预推免面试记录
  15. 什么叫faq_FAQ是什么意思啊
  16. mysql mpm_Zabbix和MPM监控MySQL
  17. 2018-08-14 UnmarshalException: 意外的元素 (uri:, local:customer)
  18. 岳父岳母-12个未接电话
  19. 179 Largest Number
  20. 关键词搜图、截图小助手——有了它妈妈再也不用担心我数据集啦

热门文章

  1. C#事件的自定义声明
  2. Atitiit java通过Exchange协议同步note 记事本 目录 1.1.1. 使用EWS(Exchange Web Service)协议读取邮件、发送邮件 1 最新问题 1 热门问题 1
  3. paip.提升用户体验-----用户注册设计
  4. paip.使用泛型时未能找到类型或命名空间名称“T
  5. Python: Flask后端与webapi
  6. 亚马逊:贝佐斯没有闹钟
  7. 【疑问】互联网公募基金的销售是繁荣,还是乱象?
  8. (转)比特币算法——SHA256算法介绍
  9. (转)用纸笔解释比特币挖矿算法原理
  10. (转)招商银行这一招,引起了各大银行的注意