java 停止服务_java中如何优雅的停止服务

强制进程退出的副作用:

缓存中的数据尚未持久化到磁盘中,导致数据丢失;

正在进行文件的write操作,没有更新完成,突然退出,导致文件损坏;

线程池的任务队列中尚有接收到的任务还没来得及处理,导致任务丢失;

数据库操作已经完成,例如账户余额更新,准备返回应答消息给客户端时,消息尚在通信线程的发送队列中排队等待发送,进程强制退出导致应答消息没有返回给客户端,客户端发起超时重试,会带来重复更新问题;

其它问题等…

解决方法:

使用ShutdownHook 钩子程序来完成善后工作

使用基于信号的进程通知机制

针对线程池的停机:

使用 DisposableBean 接口

public abstract class ExecutorConfigurationSupport extends CustomizableThreadFactory

implements DisposableBean{

@Override

public void destroy() {

shutdown();

}

/**

* Perform a shutdown on the underlying ExecutorService.

* @see java.util.concurrent.ExecutorService#shutdown()

* @see java.util.concurrent.ExecutorService#shutdownNow()

* @see #awaitTerminationIfNecessary()

*/

public void shutdown() {

if (this.waitForTasksToCompleteOnShutdown) {

this.executor.shutdown();

}

else {

this.executor.shutdownNow();

}

awaitTerminationIfNecessary();

}

/**

* Wait for the executor to terminate, according to the value of the

* {@link #setAwaitTerminationSeconds "awaitTerminationSeconds"} property.

*/

private void awaitTerminationIfNecessary() {

if (this.awaitTerminationSeconds > 0) {

try {

this.executor.awaitTermination(this.awaitTerminationSeconds, TimeUnit.SECONDS));

}

catch (InterruptedException ex) {

Thread.currentThread().interrupt();

}

}

}

}

1 通过 waitForTasksToCompleteOnShutdown 标志来控制是想立刻终止所有任务,还是等待任务执行完成后退出。

2 executor.awaitTermination(this.awaitTerminationSeconds, TimeUnit.SECONDS)); 控制等待的时间,防止任务无限期的运行(前面已经强调过了,即使是 shutdownNow 也不能保证线程一定停止运行)。

更多需要我们的思考的优雅停机策略

服务治理框架一般会考虑到优雅停机的问题。通常的做法是事先隔断流量,接着关闭应用。常见的做法是将服务节点从注册中心摘除,订阅者接收通知,移除节点,从而优雅停机;涉及到数据库操作,则可以使用事务的 ACID 特性来保证即使 crash 停机也能保证不出现异常数据,正常下线则更不用说了;又比如消息队列可以依靠 ACK 机制 + 消息持久化,或者是事务消息保障;定时任务较多的服务,处理下线则特别需要注意优雅停机的问题,因为这是一个长时间运行的服务,比其他情况更容易受停机问题的影响,可以使用幂等和标志位的方式来设计定时任务…

事务和 ACK 这类特性的支持,即使是宕机,停电,kill -9 pid 等情况,也可以使服务尽量可靠;而同样需要我们思考的还有 kill -15 pid,正常下线等情况下的停机策略。最后再补充下整理这个问题时,自己对 jvm shutdown hook 的一些理解。

shutdown hook 会保证 JVM 一直运行,直到 hook 终止 (terminated)。这也启示我们,如果接收到 kill -15 pid 命令时,执行阻塞操作,可以做到等待任务执行完成之后再关闭 JVM。同时,也解释了一些应用执行 kill -15 pid 无法退出的问题,没错,中断被阻塞了。

注:若需要平滑停止服务,我们一般可以通过ShutdownHook和Signal来实现。ShutdownHook一般比较难保证关闭任务的执行顺序,这个时候可以考虑使用Signal机制来完全托管我们关闭服务的执行顺序。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值