第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號安全,請及時綁定郵箱和手機立即綁定

Spring Boot應用中的優(yōu)雅關閉:同步與異步任務的處理方法

简短介绍

如果你的应用在某个进程尚未完成时就被终止,你可能会遇到严重的问题。尤其是对于异步进程,这种情况更为突出,它们需要更小心地处理。在这篇文章里,我将讨论如何优雅地关闭应用程序,不论是同步任务还是异步任务。

什么是优雅停机呢?

Spring Boot 应用的优雅关闭指的是以一种允许应用完成任何正在进行的任务并正确释放资源并完成所有任务的方式停止应用的过程。这确保了在途请求或后台任务能够完成,并维护数据的完整性。关闭过程在 Spring Boot 应用上下文关闭时启动,通常发生在关闭阶段。此阶段通常由各种事件触发,例如接收到终止信号、程序退出或主方法执行完毕。

_你需要记住,仅仅配置你的应用程序并不能保证优雅地停止。 ,例如,在 Kubernetes 中,你需要设置 terminationGracePeriod 来指定接收到 SIGTERM 信号以及被强制终止的 SIGKILL 信号之间的间隔时间。

概念验证

我已经将这篇帖子测试的代码上传到了Github。简而言之,有两个端点:同步端点和异步端点。每个函数都会打印一个数字,并在一个休眠1秒的循环中执行,循环迭代10,000次。

这里有一个脚本用来测试程序的优雅关闭:

    # sigterm_script.sh

    curl localhost:8080/v1/samples/sync &

    sleep 1

    PID=$(lsof -t -i:8080 | head -n 1)

    if [ -z "$PID" ]; then
        echo "应用程序未运行"
    else
        echo "正在终止进程ID为 ${PID} 的应用程序"
        kill -15 "$PID" #发送SIGTERM信号给PID进程
    fi

同步任务设置

优雅地关闭服务器程序
    服务端:  
      关闭方式: 优雅

要配置优雅地关闭,请将 server.shutdown 设置为 graceful。该设置决定了 Spring Boot 应用中的 Tomcat 服务器是否也会优雅地关闭。

    // org.springframework.boot.web.embedded.tomcat.GracefulShutdown

     private void doShutdown(GracefulShutdownCallback callback, CountDownLatch shutdownUnderway) {  
      try {  
       List<Connector> connectors = getConnectors();  
       connectors.forEach(this::close);  
       shutdownUnderway.countDown();  
       try {  
        for (Container host : this.tomcat.getEngine().findChildren()) {  
         for (Container context : host.findChildren()) {  
          while (!this.aborted && isActive(context)) {  
           Thread.sleep(50);  
          }  
          if (this.aborted) {  
           logger.info("优雅的关闭被终止,因为有一个或多个请求仍然运行");  
           callback.shutdownComplete(GracefulShutdownResult.REQUESTS_ACTIVE);  
           return;  
          }  
         }  
        }  
       }  
       catch (InterruptedException ex) {  
        Thread.currentThread().interrupt();  
       }  
       logger.info("优雅的关闭已经完成");  
       callback.shutdownComplete(GracefulShutdownResult.IDLE);  
      }  
      finally {  
       shutdownUnderway.countDown();  
      }  
     }

如果优雅关闭被启用,这段代码将会运行。它将停止接收新请求,等待所有活跃请求完成,并处理任何中断或终止信号。

每个关机阶段的启动关闭生命周期超时设置
    spring:  
      生命周期:  
        每个关闭阶段的超时时长: 90s

timeout-per-shutdown-phase 属性设定了 Spring 在每个阶段内等待 beans 完成关闭的最大时间。如果某个阶段的 beans 在指定时间内未能成功关闭,Spring 将会继续到下一阶段。默认情况下是,这个超时时间为 30 秒。

    // org.springframework.context.support.DefaultLifecycleProcessor.LifecycleGroup

      public void stop() {

    ...

       try {
        latch.await(this.timeout, TimeUnit.MILLISECONDS);
        if (latch.getCount() > 0 && !countDownBeanNames.isEmpty() && logger.isInfoEnabled()) {
         logger.info("阶段结束 " + this.phase + ",在超时 " + this.timeout + " 毫秒后仍处于运行状态的 bean 有:" + countDownBeanNames.size() + 
           " 个:" + countDownBeanNames);
        }
       }

    ...

timeout-per-shutdown-phaseLifecycleGroup 的停止方法中被使用,用于指定每个关闭阶段里,由 timeout 变量定义的最长时间,让各个 bean 在每个阶段中停止。

结果是
    ...  

    信息 10393 --- [ionShutdownHook] o.s.b.w.e.tomcat.GracefulShutdown        : 正在开始优雅的关闭。等待活跃的请求完成  
    信息 10393 --- [nio-8080-exec-1] org.example.service.SampleService        : 775  
    信息 10393 --- [nio-8080-exec-1] org.example.service.SampleService        : 776  

    ...  

    信息 10393 --- [nio-8080-exec-1] org.example.service.SampleService        : 9997  
    信息 10393 --- [nio-8080-exec-1] org.example.service.SampleService        : 9998  
    信息 10393 --- [nio-8080-exec-1] org.example.service.SampleService        : 9999  
    信息 10393 --- [tomcat-shutdown] o.s.b.w.e.tomcat.GracefulShutdown        : 优雅的关闭已经完成  

    进程因信号15(SIGTERM)中断,退出码为143

上述日志显示,在进程仍在进行中,应用程序收到了SIGTERM信号并开始优雅地结束。应用程序继续运行直到正在进行的进程完成,然后才执行关闭。

异步任务的配置
    @Bean  
    public ThreadPoolTaskExecutor threadPoolTaskExecutor() {  
        ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();  

        threadPoolTaskExecutor.setWaitForTasksToCompleteOnShutdown(true);  
        threadPoolTaskExecutor.setAwaitTerminationSeconds(AWAIT_TERMINATION_SECONDS);  
        threadPoolTaskExecutor.initialize();  

        return threadPoolTaskExecutor;  
    }

在使用异步任务时,需要在任务执行器(例如 ThreadPoolTaskExecutor)中进行额外的配置设置。设置 waitForTasksToCompleteOnShutdown 可以让执行器在终止前等待所有活动任务执行完毕。awaitTerminationSeconds 指定了在发起关闭后等待剩余任务完成的最长时间。

    // org.springframework.scheduling.concurrent.ExecutorConfigurationSupport  

     public void shutdown() {  
      if (logger.isDebugEnabled()) {  
       logger.debug("正在关闭 ExecutorService" + (this.beanName != null ? " '" + this.beanName + "'" : ""));  
      }  
      if (this.executor != null) {  
       if (this.waitForTasksToCompleteOnShutdown) {  
        this.executor.shutdown();  
       }  
       else {  
        for (Runnable remainingTask : this.executor.shutdownNow()) {  
         取消剩余任务(remainingTask);  
        }  
       }  
       awaitTerminationIfNecessary(this.executor);  
      }  
     }

ExecutorConfigurationSupport 类的 shutdown 方法中,如果 waitForTasksToCompleteOnShutdown 参数被设置为真,则调用 executor.shutdown();否则,调用 executor.shutdownNow()

shutdown 方法会开始一个有序关闭,停止接受新的任务并允许现有任务完成,而 shutdownNow 则会立即尝试停止所有正在运行的任务,并阻止等待的任务继续处理。

首先,awaitTerminationIfNecessary 方法会等待指定的 awaitTerminationSeconds 时间。因此,你需要配置这两个参数,即 awaitTerminationSecondswaitForTasksToCompleteOnShutdown,以确保在关闭前等待任务完成。否则,它会立即关闭,而不会等待任务完成。

委托执行器需注意的事项
    // org.springframework.scheduling.concurrent.ExecutorConfigurationSupport

     @Override  // 重写父类的方法
     public void destroy() {  // 销毁方法,用于执行清理操作
      shutdown();  // 执行关闭操作
     }

重要的是要指出,shutdown 方法是在 destroy 方法中被调用的,而 destroy 方法则来自重写的 DisposableBean。这意味着在使用 DelegatingSecurityContextExecutor 时,必须将 ThreadPoolTaskExecutor 定义为一个独立的 bean。如果不这样做,如下面的错误配置所示,shutdown 方法将不会在 Spring bean 的生命周期内被正确调用,这可能会导致执行程序未能按预期关闭。

  • 正确的设置
     @Bean  
     public ThreadPoolTaskExecutor 线程池任务执行器() {  
      ThreadPoolTaskExecutor 线程池 = new ThreadPoolTaskExecutor();  

      线程池.setTaskDecorator(new MDCTaskDecorator());  
      线程池.setWaitForTasksToCompleteOnShutdown(true);  
      线程池.setAwaitTerminationSeconds(AWAIT_TERMINATION_SECONDS);  
      线程池.initialize();  

      return 线程池;  
     }  

     @Bean  
     public Executor 任务执行器(final ThreadPoolTaskExecutor 线程池) {  
      return new DelegatingSecurityContextExecutor(线程池);  
     }
  • 配置错误
    @Bean  
    public Executor threadPoolTaskExecutor() {  
        ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();  

        threadPoolTaskExecutor.setTaskDecorator(new MDCTaskDecorator());  
        threadPoolTaskExecutor.setWaitForTasksToCompleteOnShutdown(true);  
        threadPoolTaskExecutor.setAwaitTerminationSeconds(AWAIT_TERMINATION_SECONDS);  
        threadPoolTaskExecutor.initialize();  

        return new DelegatingSecurityContextExecutor(threadPoolTaskExecutor);  
    }
看看结果怎么样
    INFO 10352 --- [ionShutdownHook] o.s.b.w.e.tomcat.GracefulShutdown        : 正在开始优雅的关闭过程。等待所有正在进行的请求完成  
    INFO 10352 --- [lTaskExecutor-1] org.example.service.SampleService        : 2349  
    INFO 10352 --- [lTaskExecutor-1] org.example.service.SampleService        : 2350  
    INFO 10352 --- [tomcat-shutdown] o.s.b.w.e.tomcat.GracefulShutdown        : 优雅关闭已完成  
    INFO 10352 --- [lTaskExecutor-1] org.example.service.SampleService        : 2351  

    ...  

    INFO 10352 --- [lTaskExecutor-1] org.example.service.SampleService        : 9997  
    INFO 10352 --- [lTaskExecutor-1] org.example.service.SampleService        : 9998  
    INFO 10352 --- [lTaskExecutor-1] org.example.service.SampleService        : 9999  

    进程因信号 15:SIGTERM 被中断,退出码为 143

与同步任务不同,对于异步任务,你可以在异步任务还在执行中时看到优雅的关机信息。关机过程才会在所有异步任务完成后结束。

最后

确保 Spring Boot 应用程序优雅地结束对于维护数据完整性并完成正在进行的任务至关重要。按照本文中的指南来做,您可以更有效地管理关闭过程,确保所有任务在应用终止前完成。

我真的希望这篇文章能成为你努力中的宝贵资源。感谢你花时间读我的文章 😊 如果你发现任何不准确或有任何想法想要分享,请随时告诉我一声。你的反馈对我们很有帮助,让我们可以不断学习和改进。

點擊查看更多內(nèi)容
TA 點贊

若覺得本文不錯,就分享一下吧!

評論

作者其他優(yōu)質(zhì)文章

正在加載中
  • 推薦
  • 評論
  • 收藏
  • 共同學習,寫下你的評論
感謝您的支持,我會繼續(xù)努力的~
掃碼打賞,你說多少就多少
贊賞金額會直接到老師賬戶
支付方式
打開微信掃一掃,即可進行掃碼打賞哦
今天注冊有機會得

100積分直接送

付費專欄免費學

大額優(yōu)惠券免費領

立即參與 放棄機會
微信客服

購課補貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網(wǎng)微信公眾號

舉報

0/150
提交
取消