<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      如何優(yōu)雅地停止 Spring Boot 應(yīng)用?

      首先來(lái)介紹下什么是優(yōu)雅地停止,簡(jiǎn)而言之,就是對(duì)應(yīng)用進(jìn)程發(fā)送停止指令之后,能保證正在執(zhí)行的業(yè)務(wù)操作不受影響,可以繼續(xù)完成已有請(qǐng)求的處理,但是停止接受新請(qǐng)求

      在 Spring Boot 2.3 中增加了新特性優(yōu)雅停止,目前 Spring Boot 內(nèi)置的四個(gè)嵌入式 Web 服務(wù)器(Jetty、Reactor Netty、Tomcat 和 Undertow)以及反應(yīng)式和基于 Servlet 的 Web 應(yīng)用程序都支持優(yōu)雅停止。

      下面,我們先用新版本嘗試下:

      Spring Boot 2.3 優(yōu)雅停止

      首先創(chuàng)建一個(gè) Spring Boot 的 Web 項(xiàng)目,版本選擇 2.3.0.RELEASE,Spring Boot 2.3.0.RELEASE 版本內(nèi)置的 Tomcat 為 9.0.35

      然后需要在 application.yml 中添加一些配置來(lái)啟用優(yōu)雅停止的功能:

      # 開(kāi)啟優(yōu)雅停止 Web 容器,默認(rèn)為 IMMEDIATE:立即停止
      server:
        shutdown: graceful
      
      # 最大等待時(shí)間
      spring:
        lifecycle:
          timeout-per-shutdown-phase: 30s
      

      其中,平滑關(guān)閉內(nèi)置的 Web 容器(以 Tomcat 為例)的入口代碼在 org.springframework.boot.web.embedded.tomcatGracefulShutdown 里,大概邏輯就是先停止外部的所有新請(qǐng)求,然后再處理關(guān)閉前收到的請(qǐng)求,有興趣的可以自己去看下。

      內(nèi)嵌的 Tomcat 容器平滑關(guān)閉的配置已經(jīng)完成了,那么如何優(yōu)雅關(guān)閉 Spring 容器了,就需要 Actuator 來(lái)實(shí)現(xiàn) Spring 容器的關(guān)閉了。

      然后加入 actuator 依賴,依賴如下所示:

      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-actuator</artifactId>
      </dependency>
      

      然后接著再添加一些配置來(lái)暴露 actuator 的 shutdown 接口:

      # 暴露 shutdown 接口
      management:
        endpoint:
          shutdown:
            enabled: true
        endpoints:
          web:
            exposure:
              include: shutdown
      

      其中通過(guò) Actuator 關(guān)閉 Spring 容器的入口代碼在 org.springframework.boot.actuate.context 包下 ShutdownEndpoint 類中,主要的就是執(zhí)行 doClose() 方法關(guān)閉并銷(xiāo)毀 applicationContext,有興趣的可以自己去看下。

      配置搞定后,然后在 controller 包下創(chuàng)建一個(gè) WorkController 類,并有一個(gè) work 方法,用來(lái)模擬復(fù)雜業(yè)務(wù)耗時(shí)處理流程,具體代碼如下:

      @RestController
      public class WorkController {
      
          @GetMapping("/work")
          public String work() throws InterruptedException {
              // 模擬復(fù)雜業(yè)務(wù)耗時(shí)處理流程
              Thread.sleep(10 * 1000L);
              return "success";
          }
      }
      

      然后,我們啟動(dòng)項(xiàng)目,先用 Postman 請(qǐng)求 http://localhost:8080/work 處理業(yè)務(wù):

      然后在這個(gè)時(shí)候,調(diào)用 http://localhost:8080/actuator/shutdown 就可以執(zhí)行優(yōu)雅地停止,返回結(jié)果如下:

      {
          "message": "Shutting down, bye..."
      }
      

      如果在這個(gè)時(shí)候,發(fā)起新的請(qǐng)求 http://localhost:8080/work,會(huì)沒(méi)有反應(yīng):

      再回頭看第一個(gè)請(qǐng)求,返回了結(jié)果:success

      其中有幾條服務(wù)日志如下:

      2020-05-20 23:05:15.163  INFO 102724 --- [     Thread-253] o.s.b.w.e.tomcat.GracefulShutdown        : Commencing graceful shutdown. Waiting for active requests to complete
      2020-05-20 23:05:15.287  INFO 102724 --- [tomcat-shutdown] o.s.b.w.e.tomcat.GracefulShutdown        : Graceful shutdown complete
      2020-05-20 23:05:15.295  INFO 102724 --- [     Thread-253] o.s.s.concurrent.ThreadPoolTaskExecutor  : Shutting down ExecutorService 'applicationTaskExecutor'
      

      從日志中也可以看出來(lái),當(dāng)調(diào)用 shutdown 接口的時(shí)候,會(huì)先等待請(qǐng)求處理完畢后再優(yōu)雅地停止。

      到此為止,Spring Boot 2.3 的優(yōu)雅關(guān)閉就講解完了,是不是很簡(jiǎn)單呢?如果是在之前不支持優(yōu)雅關(guān)閉的版本如何去做呢?

      Spring Boot 舊版本優(yōu)雅停止

      在這里介紹 GitHub 上 issue 里 Spring Boot 開(kāi)發(fā)者提供的一種方案:

      選取的 Spring Boot 版本為 2.2.6.RELEASE,首先要實(shí)現(xiàn) TomcatConnectorCustomizer 接口,該接口是自定義 Connector 的回調(diào)接口:

      @FunctionalInterface
      public interface TomcatConnectorCustomizer {
      
      	void customize(Connector connector);
      }
      

      除了定制 Connector 的行為,還要實(shí)現(xiàn) ApplicationListener<ContextClosedEvent> 接口,因?yàn)橐O(jiān)聽(tīng) Spring 容器的關(guān)閉事件,即當(dāng)前的 ApplicationContext 執(zhí)行 close() 方法,這樣我們就可以在請(qǐng)求處理完畢后進(jìn)行 Tomcat 線程池的關(guān)閉,具體的實(shí)現(xiàn)代碼如下:

      @Bean
      public GracefulShutdown gracefulShutdown() {
          return new GracefulShutdown();
      }
      
      private static class GracefulShutdown implements TomcatConnectorCustomizer, ApplicationListener<ContextClosedEvent> {
          private static final Logger log = LoggerFactory.getLogger(GracefulShutdown.class);
      
          private volatile Connector connector;
      
          @Override
          public void customize(Connector connector) {
              this.connector = connector;
          }
      
          @Override
          public void onApplicationEvent(ContextClosedEvent event) {
              this.connector.pause();
              Executor executor = this.connector.getProtocolHandler().getExecutor();
              if (executor instanceof ThreadPoolExecutor) {
                  try {
                      ThreadPoolExecutor threadPoolExecutor = (ThreadPoolExecutor) executor;
                      threadPoolExecutor.shutdown();
                      if (!threadPoolExecutor.awaitTermination(30, TimeUnit.SECONDS)) {
                          log.warn("Tomcat thread pool did not shut down gracefully within 30 seconds. Proceeding with forceful shutdown");
                      }
                  } catch (InterruptedException ex) {
                      Thread.currentThread().interrupt();
                  }
              }
          }
      }
      

      有了定制的 Connector 回調(diào),還需要在啟動(dòng)過(guò)程中添加到內(nèi)嵌的 Tomcat 容器中,然后等待監(jiān)聽(tīng)到關(guān)閉指令時(shí)執(zhí)行,addConnectorCustomizers 方法可以把定制的 Connector 行為添加到內(nèi)嵌的 Tomcat 中,具體代碼如下:

      @Bean
      public ConfigurableServletWebServerFactory tomcatCustomizer() {
          TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
          factory.addConnectorCustomizers(gracefulShutdown());
          return factory;
      }
      

      到此為止,內(nèi)置的 Tomcat 容器平滑關(guān)閉的操作就完成了,Spring 容器優(yōu)雅停止上面已經(jīng)說(shuō)過(guò)了,再次就不再贅述了。

      通過(guò)測(cè)試,同樣可以達(dá)到上面那樣優(yōu)雅停止的效果。

      總結(jié)

      本文主要講解了 Spring Boot 2.3 版本和舊版本的優(yōu)雅停止,避免強(qiáng)制停止導(dǎo)致正在處理的業(yè)務(wù)邏輯會(huì)被中斷,進(jìn)而導(dǎo)致產(chǎn)生業(yè)務(wù)異常的情形。

      另外使用 Actuator 的同時(shí)要注意安全問(wèn)題,比如可以通過(guò)引入 security 依賴,打開(kāi)安全限制并進(jìn)行身份驗(yàn)證,設(shè)置單獨(dú)的 Actuator 管理端口并配置只對(duì)內(nèi)網(wǎng)開(kāi)放等。

      本文的完整代碼在 https://github.com/wupeixuan/SpringBoot-Learngraceful-shutdown 目錄下。

      最好的關(guān)系就是互相成就,大家的在看、轉(zhuǎn)發(fā)、留言三連就是我創(chuàng)作的最大動(dòng)力。

      參考

      https://github.com/spring-projects/spring-boot/issues/4657

      https://github.com/wupeixuan/SpringBoot-Learn

      posted @ 2020-06-08 15:33  武培軒  閱讀(2558)  評(píng)論(3)    收藏  舉報(bào)
      主站蜘蛛池模板: 久久精品国产色蜜蜜麻豆| 激情伊人五月天久久综合| 2020国产欧洲精品网站| 午夜福利理论片高清在线| 中文字幕日韩人妻一区| 亚洲一本大道无码av天堂| 亚洲欧美日韩在线不卡| 丝袜美腿诱惑之亚洲综合网| 精品国产免费人成在线观看| 欧美人成精品网站播放| 人妻系列中文字幕精品| 99国产精品一区二区蜜臀| 国产免费AV片在线看| 国产精品午夜福利资源| 在线免费播放av观看| 日韩放荡少妇无码视频| 彭泽县| 亚洲精品精华液一区二区| 麻豆精品在线| 亚洲欧洲精品日韩av| 国产高清在线a视频大全| 亚洲欧洲日韩国内精品| 亚洲va韩国va欧美va| 日韩精品成人区中文字幕| 国产色悠悠综合在线观看| 一本一本久久a久久综合精品 | 免费看一区无码无a片www| 亚洲精品人妻中文字幕| 安泽县| 国产精品久久久一区二区三区| 欧美www在线观看| 国产精品中文字幕日韩| 青青青久热国产精品视频| 日韩人妻无码一区二区三区| 国产免费午夜福利在线播放| 在线中文字幕国产精品| 国产亚洲视频在线播放香蕉| 天堂中文8资源在线8| 国产99青青成人A在线| 昌黎县| 国产色婷婷亚洲99精品小说|