SpringBoot中異步請求的使用


一.前言

  正常的http請求是由一個線程從頭到尾來處理,當如果有請求耗時過長,而我們容器的線程數量是有限的,但所有線程都在使用,就會造成新的請求無法進行。

  異步請求可以實現當http請求進入到程序,可以先釋放容器的線程,由程序內部的線程進行處理,等處理完成后,再調回容器的線程來返回請求結果。這就可以在一定程度上提高系統的吞吐量。

二.實現

  1.使用Servlet方法來實現

@RequestMapping(value = "/importData", method = RequestMethod.POST)
public void importData(HttpServletRequest request) {
    AsyncContext asyncContext = request.startAsync();
    //設置監聽器:可設置其開始、完成、異常、超時等事件的回調處理
    asyncContext.addListener(new AsyncListener() {
      @Override
        public void onTimeout(AsyncEvent event) throws IOException {
          System.out.println("超時了...");
          //做一些超時后的相關操作...
        }
        @Override
        public void onStartAsync(AsyncEvent event) throws IOException {
          System.out.println("線程開始");
        }
        @Override
        public void onError(AsyncEvent event) throws IOException {
          System.out.println("發生錯誤:"+event.getThrowable());
        }
        @Override
        public void onComplete(AsyncEvent event) throws IOException {
          System.out.println("執行完成");
          //這里可以做一些清理資源的操作...
        }
    });
    //設置超時時間
    asyncContext.setTimeout(3000000);//5分鍾
    asyncContext.start(() -> {
        Result rm = new Result();
        try {
            System.out.println("內部線程:" + Thread.currentThread().getName());
            asyncContext.getResponse().setCharacterEncoding("utf-8");
            asyncContext.getResponse().setContentType("text/html;charset=UTF-8");
            asyncContext.getResponse().getWriter().println("返回成功");
        } catch (Exception e) {
            System.out.println("異常:" + e);
        }
        //異步請求完成通知
        //此時整個請求才完成
        asyncContext.complete();
    });
    //此時之類 request的線程連接已經釋放了
    System.out.println("主線程:" + Thread.currentThread().getName());
}

   2.在SpringBoot中可以使用Callable、DeferredResult、WebAysncTask。這里只舉Callable的代碼例子。

@RequestMapping("/callable")
public Callable<String> callable() {
    log.info("外部線程:" + Thread.currentThread().getName());
    return new Callable<String>() {

        @Override
        public String call() throws Exception {
            log.info("內部線程:" + Thread.currentThread().getName());
            return "callable!";
        }
    };
}

三.總結

  1.異步請求可以有效提供系統的吞吐量。

  2.異步請求是通過容器線程和程序線程的分配來提高效率。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM