<del id="nnjnj"></del><track id="nnjnj"></track>

<p id="nnjnj"></p>

<address id="nnjnj"></address>

    <pre id="nnjnj"><pre id="nnjnj"></pre></pre>

      <noframes id="nnjnj"><ruby id="nnjnj"><ruby id="nnjnj"></ruby></ruby>

      • 自動秒收錄
      • 軟件:1973
      • 資訊:57811|
      • 收錄網站:279872|

      IT精英團

      7 種提升Spring Boot吞吐量神技!

      7 種提升Spring Boot吞吐量神技!

      瀏覽次數:
      評論次數:
      編輯: 景同
      信息來源: ITPUB
      更新日期: 2022-05-05 18:33:09
      摘要

      一、異步執行實現方式二種:1.使用異步注解@aysnc、啟動類:添加@EnableAsync注解2.JDK8本身有一個非常好用的Future類——CompletableFuture@AllArg

      • 正文開始
      • 相關閱讀
      • 推薦作品

      一、異步執行

      實現方式二種:

      1.使用異步注解@aysnc,啟動類:添加@啟用異步注解2.JDK 8本身有一個非常好用的將來的類—— completablefuture @ allargsconstructorpublicclassaksthreadimplementsrunnable { privateCompletableFutureInteger re=null;public void run(){ int myre=;試試{ myRe=re。get()* re。get();} catch(Exception e){ e . printstacktrace();}系統。出去。println(邁雷);} publistativoidmain(String[]args)throwsInterruptedException { finalCompletableFutureInteger future=newCompletableFuture();新線程(newAskThread(未來))。start();//模擬長時間的計算過程線程。睡眠(1000);//告知完成結果未來.完成(六十);}}在該示例中,啟動一個線程,此時要求線程對象還沒有拿到它需要的數據,執行到myRe=re.get() * re.get()會阻塞。我們用休眠一秒來模擬一個長時間的計算過程,并將計算結果告訴將來的執行結果,問線程線程將會繼續執行。如果您正在學習Spring Boot,

      那么推薦一個連載多年還在繼續更新的免費教程:http://blog.didispace.com/spring-boot-learning-2x/

      public class Calc {
          public static Integer calc(Integer para) {
              try {
                  //模擬一個長時間的執行
                  Thread.sleep(1000);
              } catch (InterruptedException e) {
                  e.printStackTrace();
              }
              return para * para;
          }

          public static void main(String[] args) throws ExecutionException, InterruptedException {
              final CompletableFuture<Void> future = CompletableFuture.supplyAsync(() -> calc(50))
                      .thenApply((i) -> Integer.toString(i))
                      .thenApply((str) -> "\"" + str + "\"")
                      .thenAccept(System.out::println);
              future.get();
          }
      }

      CompletableFuture.supplyAsync方法構造一個CompletableFuture實例,在supplyAsync()方法中,它會在一個新線程中,執行傳入的參數。在這里它會執行calc()方法,這個方法可能是比較慢的,但這并不影響CompletableFuture實例的構造速度,supplyAsync()會立即返回。

      而返回的CompletableFuture實例就可以作為這次調用的契約,在將來任何場合,用于獲得最終的計算結果。最近整理了一份最新的面試資料,里面收錄了2021年各個大廠的面試題,打算跳槽的小伙伴不要錯過,點擊領取吧!

      supplyAsync用于提供返回值的情況,CompletableFuture還有一個不需要返回值的異步調用方法runAsync(Runnable runnable),一般我們在優化Controller時,使用這個方法比較多。這兩個方法如果在不指定線程池的情況下,都是在ForkJoinPool.common線程池中執行,而這個線程池中的所有線程都是Daemon(守護)線程,所以,當主線程結束時,這些線程無論執行完畢都會退出系統。

      核心代碼:

      CompletableFuture.runAsync(() ->
         this.afterBetProcessor(betRequest,betDetailResult,appUser,id)
      );

      異步調用使用Callable來實現

      @RestController  
      public class HelloController {
        
          private static final Logger logger = LoggerFactory.getLogger(HelloController.class);
            
          @Autowired  
          private HelloService hello;
        
          @GetMapping("/helloworld")
          public String helloWorldController() {
              return hello.sayHello();
          }
        
          /**
           * 異步調用restful
           * 當controller返回值是Callable的時候,springmvc就會啟動一個線程將Callable交給TaskExecutor去處理
           * 然后DispatcherServlet還有所有的spring攔截器都退出主線程,然后把response保持打開的狀態
           * 當Callable執行結束之后,springmvc就會重新啟動分配一個request請求,然后DispatcherServlet就重新
           * 調用和處理Callable異步執行的返回結果, 然后返回視圖
           *
           * @return
           */  
          @GetMapping("/hello")
          public Callable<String> helloController() {
              logger.info(Thread.currentThread().getName() + " 進入helloController方法");
              Callable<String> callable = new Callable<String>() {
        
                  @Override  
                  public String call() throws Exception {
                      logger.info(Thread.currentThread().getName() + " 進入call方法");
                      String say = hello.sayHello();
                      logger.info(Thread.currentThread().getName() + " 從helloService方法返回");
                      return say;
                  }
              };
              logger.info(Thread.currentThread().getName() + " 從helloController方法返回");
              return callable;
          }
      }

      異步調用的方式 WebAsyncTask

      @RestController  
      public class HelloController {
        
          private static final Logger logger = LoggerFactory.getLogger(HelloController.class);
            
          @Autowired  
          private HelloService hello;
        
              /**
           * 帶超時時間的異步請求 通過WebAsyncTask自定義客戶端超時間
           *
           * @return
           */  
          @GetMapping("/world")
          public WebAsyncTask<String> worldController() {
              logger.info(Thread.currentThread().getName() + " 進入helloController方法");
        
              // 3s鐘沒返回,則認為超時
              WebAsyncTask<String> webAsyncTask = new WebAsyncTask<>(3000, new Callable<String>() {
        
                  @Override  
                  public String call() throws Exception {
                      logger.info(Thread.currentThread().getName() + " 進入call方法");
                      String say = hello.sayHello();
                      logger.info(Thread.currentThread().getName() + " 從helloService方法返回");
                      return say;
                  }
              });
              logger.info(Thread.currentThread().getName() + " 從helloController方法返回");
        
              webAsyncTask.onCompletion(new Runnable() {
        
                  @Override  
                  public void run() {
                      logger.info(Thread.currentThread().getName() + " 執行完畢");
                  }
              });
        
              webAsyncTask.onTimeout(new Callable<String>() {
        
                  @Override  
                  public String call() throws Exception {
                      logger.info(Thread.currentThread().getName() + " onTimeout");
                      // 超時的時候,直接拋異常,讓外層統一處理超時異常
                      throw new TimeoutException("調用超時");
                  }
              });
              return webAsyncTask;
          }
        
          /**
           * 異步調用,異常處理,詳細的處理流程見MyExceptionHandler類
           *
           * @return
           */  
          @GetMapping("/exception")
          public WebAsyncTask<String> exceptionController() {
              logger.info(Thread.currentThread().getName() + " 進入helloController方法");
              Callable<String> callable = new Callable<String>() {
        
                  @Override  
                  public String call() throws Exception {
                      logger.info(Thread.currentThread().getName() + " 進入call方法");
                      throw new TimeoutException("調用超時!");
                  }
              };
              logger.info(Thread.currentThread().getName() + " 從helloController方法返回");
              return new WebAsyncTask<>(20000, callable);
          }
        
      }
      二、增加內嵌Tomcat的最大連接數
      @Configuration
      public class TomcatConfig {
          @Bean
          public ConfigurableServletWebServerFactory webServerFactory() {
              TomcatServletWebServerFactory tomcatFactory = new TomcatServletWebServerFactory();
              tomcatFactory.addConnectorCustomizers(new MyTomcatConnectorCustomizer());
              tomcatFactory.setPort(8005);
              tomcatFactory.setContextPath("/api-g");
              return tomcatFactory;
          }
          class MyTomcatConnectorCustomizer implements TomcatConnectorCustomizer {
              public void customize(Connector connector) {
                  Http11NioProtocol protocol = (Http11NioProtocol) connector.getProtocolHandler();
                  //設置最大連接數
                  protocol.setMaxConnections(20000);
                  //設置最大線程數
                  protocol.setMaxThreads(2000);
                  protocol.setConnectionTimeout(30000);
              }
          }

      }


      三、使用@ComponentScan()定位掃包比@SpringBootApplication掃包更快
      四、默認tomcat容器改為Undertow(Jboss下的服務器,Tomcat吞吐量5000,Undertow吞吐量8000)
      <exclusions>
        <exclusion>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-tomcat</artifactId>
        </exclusion>
      </exclusions>


      改為:

      <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-undertow</artifactId>
      </dependency>
      五、使用 BufferedWriter 進行緩沖
      六、Deferred方式實現異步調用
      @RestController
      public class AsyncDeferredController {
          private final Logger logger = LoggerFactory.getLogger(this.getClass());
          private final LongTimeTask taskService;
          
          @Autowired
          public AsyncDeferredController(LongTimeTask taskService) {
              this.taskService = taskService;
          }
          
          @GetMapping("/deferred")
          public DeferredResult<String> executeSlowTask() {
              logger.info(Thread.currentThread().getName() + "進入executeSlowTask方法");
              DeferredResult<String> deferredResult = new DeferredResult<>();
              // 調用長時間執行任務
              taskService.execute(deferredResult);
              // 當長時間任務中使用deferred.setResult("world");這個方法時,會從長時間任務中返回,繼續controller里面的流程
              logger.info(Thread.currentThread().getName() + "從executeSlowTask方法返回");
              // 超時的回調方法
              deferredResult.onTimeout(new Runnable(){
        
         @Override
         public void run() {
          logger.info(Thread.currentThread().getName() + " onTimeout");
          // 返回超時信息
          deferredResult.setErrorResult("time out!");
         }
        });
              
              // 處理完成的回調方法,無論是超時還是處理成功,都會進入這個回調方法
              deferredResult.onCompletion(new Runnable(){
        
         @Override
         public void run() {
          logger.info(Thread.currentThread().getName() + " onCompletion");
         }
        });
              
              return deferredResult;
          }
      }


      七、異步調用可以使用AsyncHandlerInterceptor進行攔截

      @Component
      public class MyAsyncHandlerInterceptor implements AsyncHandlerInterceptor {
       
       private static final Logger logger = LoggerFactory.getLogger(MyAsyncHandlerInterceptor.class);
       
       @Override
       public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
         throws Exception {
        return true;
       }
       
       @Override
       public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
         ModelAndView modelAndView) throws Exception {
      // HandlerMethod handlerMethod = (HandlerMethod) handler;
        logger.info(Thread.currentThread().getName()+ "服務調用完成,返回結果給客戶端");
       }
       
       @Override
       public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
         throws Exception {
        if(null != ex){
         System.out.println("發生異常:"+ex.getMessage());
        }
       }
       
       @Override
       public void afterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response, Object handler)
         throws Exception {
        
        // 攔截之后,重新寫回數據,將原來的hello world換成如下字符串
        String resp = "my name is chhliu!";
        response.setContentLength(resp.length());
        response.getOutputStream().write(resp.getBytes());
        
        logger.info(Thread.currentThread().getName() + " 進入afterConcurrentHandlingStarted方法");
       }
       
      }


      參考
      • https://my.oschina.net/u/3768341/blog/3001731

      • https://blog.csdn.net/liuchuanhong1/article/details/78744138

      如何在Linux下擴展XFS根分區
      ? 上一篇 2022-05-05
      低代碼實時倉儲系統的設計與實踐
      下一篇 ? 2022-05-05
      • 如何在Ubuntu中保留文件系統并備份當前開發板鏡像
        0閱讀 0條評論 個贊
        在Ubuntu保留文件系統或者說備份當前開發板鏡像的需求在不斷增加。比如Ubuntu文件系統需要安裝庫文件的話直接使用apt-get工具就可以下載,但由于需要下載的核心板較多,比較費時間,這時需要將安……
      • 國產核心板全志T507助力消防系統升級
        0閱讀 0條評論 個贊
        9月16日下午,位于湖南長沙市區內的中國電信大樓發生火災,建筑高度218米,現場濃煙滾滾,數十層樓體燃燒劇烈。消防救援人員趕到現場后很快將火勢控制住,目前大樓火勢已被撲滅,所幸未發現人員傷亡。湖南電信……
      • 教大家如何處理Spring Boot易流中的用戶和群體!
        0閱讀 0條評論 個贊
        1.準備工作2.用戶操作2.1添加用戶2.2修改用戶2.3刪除用戶2.4查詢用戶3.組操作3.1添加組3.2修改組3.3刪除組3.4查詢組4.查看表詳情雖然說我們在實際開發中,……
      • 從PG15開始WAL壓縮優化
        0閱讀 0條評論 個贊
        PG15傳聞中的超級令人激動的功能大多數跳票了,年初我也寫過一個關于PG15新功能跳票的文章。PG15BETA已經發出幾個月了,似乎PG15里令人激動人心的功能不多,不過從長長的新功能列表里,……
      • 深入了解美團葉子發射器開源方案
        0閱讀 0條評論 個贊
        大家好,我是樹哥。之前我們有聊過「如何設計一個分布式ID發號器」,其中有講過4種解決方案,分別是:UUID類雪花算法數據庫自增主鍵Redis原子自增美團以第2、3種解決方案為基礎,開發出……
      發表評論 共有條評論
      用戶名: 密碼:
      驗證碼: 匿名發表
      • k8s網絡持久存儲的StorageClass(如何一步步實現動態持久存儲)
        0閱讀 0條評論 個贊
        StorageClass的作用:創建pv時,先要創建各種固定大小的PV,而這些PV都是手動創建的,當業務量上來時,需要創建很多的PV,過程非常麻煩。而且開發人員在申請PVC資源時,還不一定有匹配條件的……
      • 舉例說明庫伯內特公司的豆莢核心資源
        3閱讀 0條評論 個贊
        目錄一、Pod定義二、Pod入門yaml描述文件三、共享NetworkNamespace四、共享PID五、容器生命周期六、初始化容器6.1、簡介6.2、與普通容器的區別6.3、實驗七、Pod探針7.1……
      • smile——Java機器學習引擎
        2閱讀 0條評論 個贊
        資源https://haifengl.github.io/https://github.com/haifengl/smile介紹Smile(統計機器智能和學習引擎)是一個基于Java和Scala的快速……
      • Velox簡介:一個開源的統一執行引擎
        0閱讀 0條評論 個贊
        ?Meta正在引入Velox,這是一個開源的統一執行引擎(unifiedexecutionengine),旨在加速數據管理系統和簡化其開發。?Velox正在積極開發中,Meta在2022……
      • 關于Redis在windows上運行的問題和fork函數
        0閱讀 0條評論 個贊
        Redis在將數據庫進行持久化操作時,需要fork一個進程,但是windows并不支持fork,導致在持久化操作期間,Redis必須阻塞所有的客戶端直至持久化操作完成。微軟的一些工程師花費時間在解決在……
      • [PostgreSql]生產級數據庫安裝需要考慮哪些問題?
        0閱讀 0條評論 個贊
        大家好,我是字母哥(coder)!我讓公司的小伙伴寫一個生產級別的PostgreSQL的安裝文檔,結果他和我說:“不是用一個命令就能安裝好么?還用寫文檔么?”。我知道他想說的是這個命令:yumins……
      • [設計模式] Java設計模式-工廠模式
        3閱讀 0條評論 個贊
        目錄【設計模式】Java設計模式-工廠模式簡介1、普通工廠(SimpleFactory)模式①、定義類②、定義簡單的工廠類③、實例2、抽象工廠(AbstractFactory)模式①、定義類②、……
      • 卡夫卡數據丟失問題優化總結及重復消費原因分析(二)
        0閱讀 0條評論 個贊
        .css-1yuhvjn{margin-top:16px;}.css-3jt6os.FileLinkCard{-webkit-align-items:center;-webkit-box-align……
      • 全網最全Linux命令匯總!(史上最全 推薦收藏)
        7閱讀 0條評論 個贊
        今天,給小伙伴們帶來一篇史上最全Linux命令總結的文章,命令有點多,建議小伙伴們先收藏后閱讀。好了,我們開始今天的正文。列出目錄內容ls-a:顯示所有文件(包括隱藏文件);ls-l:顯示詳細……
      • 如何不寫YAML來管理Kubernetes應用程序?
        2閱讀 0條評論 個贊
        Kubernetes將自身邊界內的事物都抽象為資源。其中的主要部分,是以Deployment、StatefulSet為代表的workload工作負載控制器,其他各類資源都圍繞這些主要的資源工……
      • 每分鐘寫6億條數據 攜程監控系統Dashboard存儲升級實踐
        0閱讀 0條評論 個贊
        .css-1yuhvjn{margin-top:16px;}.css-3jt6os.FileLinkCard{-webkit-align-items:center;-webkit-box-align……
      • 卡夫卡數據丟失問題優化總結及重復消費原因分析(一)
        0閱讀 0條評論 個贊
        .css-1yuhvjn{margin-top:16px;}.css-3jt6os.FileLinkCard{-webkit-align-items:center;-webkit-box-align……
      • Python自學教程7:字典類型有什么用
        0閱讀 0條評論 個贊
        字典是Python中的一個重要操作,如果字典玩得順,很多其他的數據類型就可以一通百通。Python字典的定義字典使用一對大括號進行定義,鍵值對之間使用逗號隔開,鍵和值使用冒號分隔。鍵必須是不可變類型,……
      • SQLServer自動化運維系列監控磁盤剩余空間和SQLServer錯誤日志(PowerShell)
        0閱讀 0條評論 個贊
        需求描述在我們的生產環境中,大部分情況下需要有自己的運維體制,包括自己健康狀態的檢測等。如果發生異常,需要提前預警的,通知形式一般為發郵件告知。在所有的自檢流程中最基礎的一個就是磁盤剩余空間檢測。作為……
      • 深入了解美團葉子發射器開源方案
        0閱讀 0條評論 個贊
        大家好,我是樹哥。之前我們有聊過「如何設計一個分布式ID發號器」,其中有講過4種解決方案,分別是:UUID類雪花算法數據庫自增主鍵Redis原子自增美團以第2、3種解決方案為基礎,開發出……
      • 拓撲嶺CEO雷鵬:創業不只是技術
        0閱讀 0條評論 個贊
        云計算的出現,加速了企業信息技術的發展。數據庫是最常用的基礎軟件之一,它通常能提供計算和存儲的能力。雖然分布式數據庫也做到了很好的擴展性,但它不能算是「云原生」?!冈圃鷶祿臁沟暮诵?,是要設計一種更……
      • Java可以重新鎖定的那些東西(1)
        0閱讀 0條評論 個贊
        本文主要包含的內容:可重入鎖(ReedtrantLock)、公平鎖、非公平鎖、可重入性、同步隊列、CAS等概念的理解顯式鎖……
      • 在一本書中閱讀所有的Hive Sql(20 000字的最完整解釋)
        0閱讀 0條評論 個贊
        HiveSql大全本文基本涵蓋了Hive日常使用的所有SQL,因為SQL太多,所以將SQL進行了如下分類:一、DDL語句(數據定義語句):對數據庫的操作:包含創建、修改數據庫對數據表的操作:分……
      • 金牛座入門 MVC微服務框架開發教程
        0閱讀 0條評論 個贊
        前言:對于Taurus.MVC的微服務的注冊中心而言:什么樣的應用中心,有權利注冊服務?什么樣的網關中心,有權利調取服務列表?在默認沒有進行相關配置時,只要引用Taurus.MVC的框架,都擁有該權限……
      • 詳細解釋MySQL隔離級別
        0閱讀 0條評論 個贊
        一個事務具有ACID特性,也就是(Atomicity、Consistency、Isolation、Durability,即原子性、一致性、隔離性、持久性),本文主要講解一下其中的Isolation,也……
      最近發布資訊
      更多
      警花高潮嗷嗷叫
      <del id="nnjnj"></del><track id="nnjnj"></track>

      <p id="nnjnj"></p>

      <address id="nnjnj"></address>

        <pre id="nnjnj"><pre id="nnjnj"></pre></pre>

          <noframes id="nnjnj"><ruby id="nnjnj"><ruby id="nnjnj"></ruby></ruby>