美文网首页
java中如何优雅的停止服务

java中如何优雅的停止服务

作者: 不怕天黑_0819 | 来源:发表于2020-08-30 10:46 被阅读0次

强制进程退出的副作用:

  • 缓存中的数据尚未持久化到磁盘中,导致数据丢失;
  • 正在进行文件的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机制来完全托管我们关闭服务的执行顺序。

参考链接:
https://www.cnkirito.moe/gracefully-shutdown/

https://www.cnblogs.com/panchanggui/p/9806266.html

https://juejin.im/post/6844903814181421064

相关文章

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

    强制进程退出的副作用: 缓存中的数据尚未持久化到磁盘中,导致数据丢失; 正在进行文件的write操作,没有更新完成...

  • 一个简单的带中断策略的Thread用例

    使用: 如何优雅的"停止"一个正在运行的JAVA线程如何正确地停止一个线程?关闭线程的正确方法:“优雅”的中断Ja...

  • SpringCloud-Eureka[优雅停服]

    本文我们来介绍下在Eureka中我们如何比较方便的停止服务,并且将服务从注册中心中移除 Eureka的优雅停服 一...

  • SparkStreaming如何优雅的停止服务

    我们都知道SparkStreaming程序是一个长服务,一旦运转起来不会轻易停掉,那么如果我们想要停掉正在运行的程...

  • java 中优雅的停止线程

    方法一 轮询一个volatile的boolean变量 方法二 线程中断 超时停止 有时候线程在轮询的时候,由于内部...

  • Exception

    Java 中 9 个处理 Exception 的最佳实践 Java 中的异常和处理详解 如何优雅的设计 Java ...

  • Java 优雅退出

    前言 先思考几个问题 Java 服务为什么会挂掉? 什么情况 Java 进程会挂掉? Java 进程挂掉如何做优雅...

  • Spring Boot如何优雅地停止服务

    作者:黄青石来源:博客园 前言 在使用Springboot的时候,都要涉及到服务的停止和启动,当我们停止服务的时候...

  • 031-优雅停止服务

    由于 SpringBoot 是一个微服务框架,其生产部署的方式也需要尽可能的简单,与常规的 Web 应用有着一个巨...

  • 如何优雅的配置 Java 微服务

    本节我们会学到如何以及为什么要实现外部化微服务应用配置。 具体来说,你将学习如何使用 Kubernetes Con...

网友评论

      本文标题:java中如何优雅的停止服务

      本文链接:https://www.haomeiwen.com/subject/bfossktx.html