首页 > 代码库 > 26. 后台程序如何优雅的退出
26. 后台程序如何优雅的退出
一. 前言
项目初期我们可以使用kill -9 pid的方法来杀死后台服务进程,然后重新部署。
但是随着时间发展,这种简单粗暴的方法会有一些问题:
如何在退出时清理一些资源?
如果某个请求执行操作到一半,直接被退出了,就会造成脏数据。
如何给客户端正确的反馈?
二. Java虚拟机退出钩子
虚拟机允许在退出的时候执行钩子程序,那么我们可以在这个方法里面作一些释放资源的操作,如下:
System.out.println("add hook..."); Thread shutdownThread = new Thread(new Runnable() { @Override public void run() { System.out.println("hook running.." + System.currentTimeMillis()); try { Thread.sleep(10000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("hook sleep done..." + System.currentTimeMillis()); } }); Runtime.getRuntime().addShutdownHook(shutdownThread);
三. tomcat的unloadDelay属性
这个属性的意思是tomcat留给请求执行的时间,默认只有2秒,也就是执行./shundown.sh之后,请求处理只有2秒的时间。如果没有及时返回给客户端,那么就会返回客户端503错误。
apache-tomcat-9.0.0.M22-src/java/org/apache/catalina/core/StandardWrapper.java
/** * Wait time for servlet unload in ms. */ protected long unloadDelay = 2000; public synchronized void unload() throws ServletException { // Nothing to do if we have never loaded the instance if (!singleThreadModel && (instance == null)) { log.info("instance run..."); return; } unloading = true; log.info("countAllocated.get(): " + countAllocated.get()); // Loaf a while if the current instance is allocated // (possibly more than once if non-STM) if (countAllocated.get() > 0) { int nRetries = 0; long delay = unloadDelay / 20; System.out.println("unloadDelay: " + unloadDelay); log.info("unloadDelay 2222: " + unloadDelay); while ((nRetries < 21) && (countAllocated.get() > 0)) { if ((nRetries % 10) == 0) { log.info(sm.getString("standardWrapper.waiting", countAllocated.toString(), getName())); } try { Thread.sleep(delay); } catch (InterruptedException e) { // Ignore } nRetries++; } } }
这段代码它会把unloadDelay分成20份,然后循环20次检查请求是否已经结束。
unloadDelay默认是2000ms,也就是2秒钟.
这样写的好处是即使配置的unloadDelay时间很长,但是如果请求很快结束,那么它也不会等待配置的unloadDelay时间,它可以提前退出服务。
如果请求在unloadDelay时间内处理完请求,那么客户端就可以接受到正常的结果。
四. unloadDelay配置
在tomcat的conf目录下的context.xml中可以配置,如下:
<Context unloadDelay="20000"> ... </Context>
五. springboot发送http请求关闭服务
在pom.xml中配置
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId></dependency>
在application.properties中配置
#启用 shutdownendpoints.shutdown.enabled=true #禁用密码验证 endpoints.shutdown.sensitive=false
发送http关闭命令
curl -X POST host:port/shutdown
得到的返回消息如下:
{"message":"Shutting down, bye..."}
发送http消息后,它会拒绝新的请求,2秒内让已有请求执行完毕,清理资源。
本文出自 “www.bogo.com” 博客,请务必保留此出处http://483181.blog.51cto.com/473181/1943154
26. 后台程序如何优雅的退出