python 程序停止打印日志_停止 Spring Boot 服务的几种优雅姿势

ce0305d324a4fa5f892634057416599b.png

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

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

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

  <dependency>

<groupId>org.springframework.bootgroupId>

<artifactId>spring-boot-starter-actuatorartifactId>

dependency>

然后将 shutdown 节点打开,也将 /actuator/shutdown 暴露 web 访问也设置上,除了 shutdown 之外还有 health, info 的 web 访问都打开的话将 management.endpoints.web.exposure.include=* 就可以。将如下配置设置到 application.properties 里边,设置一下服务的端口号为 3333。

server.port=3333

management.endpoint.shutdown.enabled=true

management.endpoints.web.exposure.include=shutdown

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

package com.hqs.springboot.shutdowndemo.bean;

import javax.annotation.PreDestroy;

/**

* @author huangqingshi

* @Date 2019-08-17

*/

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;

/**

* @author huangqingshi

* @Date 2019-08-17

*/

@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();

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

/* 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。

/* 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;

/**

* @author huangqingshi

* @Date 2019-08-17

*/

@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;

}

}

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

总结

以上这几种方法实现的话比较简单,但是真实工作中还需要考虑的点还很多,比如需要保护暴露的点不被别人利用,一般要加一些防火墙,或者只在内网使用,保证程序安全。

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

所谓技多不压身,我们所读过的每一本书,所学过的每一门语言,在未来指不定都能给我们意想不到的回馈呢。其实做为一个开发者,有一个学习的氛围跟一个交流圈子特别重要这里我推荐一个Java学习交流群私信小编回复JAVA获得进群资料,不管你是小白还是大牛欢迎入驻,大家一起交流成长。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/434877.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

批量导出部分依赖图(PDP)

部分依赖图 (PDP) 和个体条件期望 (ICE) 图可用于可视化和分析目标响应1与一组感兴趣的输入特征之间的交互。 部分依赖图 (PDP) 显示了目标响应与一组感兴趣的输入特征之间的依赖关系&#xff0c;边缘化了所有其他输入特征&#xff08;“补充”特征&#xff09;的值。直观地说…

arcgis已知两点投影坐标求距离

问题&#xff1a; 已知中心点坐标&#xff0c;求个点与中心点坐标的距离 解决方法如下&#xff1a; 新建字段 在新建字段上右键字段计算器 利用字段计算器进行两点间距离计算 不懂问题请进群交流询问相关知识点

【原创】StreamInsight查询系列(十九)——查询模式之检测异常

上篇文章介绍了查询模式中如何发现趋势&#xff0c;这篇博文将介绍StreamInsight中如何检测异常。 测试数据准备 为了方便测试查询&#xff0c;我们首先准备一个静态的测试数据源&#xff1a;var now DateTime.Parse("09/12/2011 8:57:00 PM"); var input new[] {n…

SIP协议详解

SIP协议概念** 会话启动协议SIP&#xff08;Session Initiation Protocol&#xff09;是一个在IP网络上进行多媒体通信的应用层控制协议&#xff0c;它被用来创 建、修改、和终结一个或多个参加者参加的会话进程。 **SIP协议可用于发起会话&#xff0c;也可以用于邀请成员加入…

arcgis判断两个字段是否相等

def a(b,c):if(bc):return 1else:return 0 不懂问题请进群交流

一元三次方程重根判别式_许兴华——关于复数集中解一元二次方程的问题

在学习复数时&#xff0c;最近有个别比较好学的同学提出一个问题&#xff1a;“对于复数系数一元二次方程&#xff0c;是否可以用求根公式求解呢&#xff1f;”——回答是肯定的&#xff01;关于复数集中解一元二次方程的问题。其实&#xff0c;在复数集内解关于x的一元二次方程…

arcgis批量将栅格里的nodata转为0

新建模型 修改名称 在arcgis的工具箱中新建一个模型&#xff0c;具体模型如下 模型里的具体参数如下 1.栅格计算器 2.输出路径&#xff0c;%—%这样的的输出可以保留之前的文件的名称 不懂问题请进群交流

arcgis中制作复杂符号

简介 在arcgis制图中常会遇到复杂的制图符号,如下 通过平常的代码显示并不会显示原图这样的效果,接下来我们开始解决改问题 主要思想: 通过字体文件将其显示 所以的软件: arcgis和FontCreator FontCreator软件下载链接

根据rtk参数在arcgis中进行可视化

RTK原始文件 通过原始文件发现&#xff0c;arcgis中并没有中央经线是113的CGS2000投影坐标&#xff0c;所以此处需要进行自定义投影转换 不懂问题请进群交流

解决mapgis转位置范围偏差过大的问题(比例尺)

问题描述: 在mapgis投影坐标转地理坐标,结果发现地理坐标错误 这样的地理坐标很明显是错误的,发现经度位置些许有些偏差,纬度有大幅度偏差 问题主要出现在在调整投影参数的比例尺分母不正确 解决: 找一个相似研究范围的mapgis文件或者shp文件 方法1(mapgis文件): …

有意思的小学数学竞赛题-2

刚刚在matrix67上看到一篇很有意思的帖子&#xff0c;原文http://www.matrix67.com/blog/archives/4485 我老早就写过一个经典的小学几何题。如果你还没看过这个问题&#xff0c;你一定要去看看。一个小学奥数老师曾 经告诉我&#xff0c;当年带领学生参加这次竞赛时&#xff0…

利用python处理中国地面气候资料日值数据集(V3.0)

原始文件 数据链接 00年到18年气象数据&#xff0c;但是未进行处理-数据集文档类资源-CSDN下载00年到18年气象数据&#xff0c;但是未进行处理&#xff0c;如果需要处理好的数据&#xff08;execl和shp&#xff09;&#xff0c;请查看本博主其他更多下载资源、学习资料请访问C…

mapgis转shp左右位置偏差

问题描述 问题原因 一般情况下&#xff0c;投影中心经度不会出现这么复杂的数字&#xff0c;一般都是1110000&#xff0c;1170000&#xff0c;前3个数字为整数后四个数字为0 问题解决 主要思想&#xff1a;通常相差的经纬度&#xff0c;调整投影中心点经度 解决步骤 1.试图…

Oracle Database Appliance

转载&#xff1a;http://www.hellodb.net/2011/09/oracle-database-appliance.html自从Oracle收购了SUN&#xff0c;不仅仅得到了MySQL&#xff0c;Java&#xff0c;Solaris等&#xff0c;还得到了SUN的硬件产品&#xff0c;真正成为了一家软硬通杀的服务提供商。这几年&#x…

arcgis中的插值分析了解

1.前言 打开arcgis工具箱我们可以发现arcgis为我们提供了多种插值分析的工具&#xff0c;克里金插值、反距离权重插值、样条函数插值等&#xff0c;具体如图所示 在工具箱中除地形转栅格和通过文件实现地形转栅格是用来绘制dem数据&#xff0c;其他就是我们日常研究所用的插值工…

解决MAPGIS导出数据乱码

所需软件&#xff1a; MAPGIS6.7 MAPGIS10版本以上 MAPGIS开发入门向导手册.zip-行业报告文档类资源-CSDN下载MAPGIS开发入门向导手册.zip更多下载资源、学习资料请访问CSDN下载频道.https://download.csdn.net/download/qq_39397927/85321238ArcGIS 问题描述 在mapgis中的…

突破select的FD_SETSIZE限制

前言&#xff1a; 在很多比较各种网络模型的文章中&#xff0c;但凡提到select模型时&#xff0c;都会说select受限于轮询的套接字数量&#xff0c;这个 数量也就是系统头文件中定义的FD_SETSIZE值(例如64)。但事实上这个算不上真的限制。 C语言的偏方&#xff1a; 在C语…

袋装树和随机森林的区别

装袋法建树的时候是将所有预测变量都考虑进去&#xff0c; 而随机森林则是考虑每一个分裂点时&#xff0c;都是从所有的预测变量p中随机选取m个预测变量&#xff0c;分裂点所用的预测变量只能从这m个变量中选择。

arcgis中的SetNull(,)函数使用

SetNull(设置条件&#xff0c;将条件之内的值变为nodata,条件之外的值处理) 例如&#xff1a; 1.setnull("DEM"500,"DEM"),将DEM中值为500的数据赋为空&#xff0c;其他保留原值 2.setnull("DEM">500,"DEM"),将DEM中值大于500的…

如何处理MODIS蒸散数据(ET)中的填充值(仅作参考)

该处理过程是个人想法&#xff0c;仅做参考&#xff0c;如果想要等到比精确的蒸散数据请参考《京津唐地区城市扩张对地表蒸散发的影响》中蒸散的计算过程。 MOD16A3 第 6 版蒸发蒸腾/潜热通量产品是按 500 米 (m) 像素分辨率生成的年度复合数据集。 根据《京津唐地区城市扩张对…