異步Servlet的理解與實踐

AsyncContext理解

Servlet 3.0(JSR315)定義了Servlet/Filter的異步特性規範.
怎麼理解"異步Servlet/Filter"及其使用情景?api

Servlet3.0之前

流程:

  1. 容器初始化ServletRequest與ServletResponse對象.
  2. 容器調用Servlet實例的service(ServletRequest, ServletResponse)執行業務邏輯.
  3. 容器Commit ServletResponse, 將響應結果寫回客戶端並關閉鏈接.異步

    • Servlet接口定義
    public interface Servlet {
        public void init(ServletConfig config) throws ServletException;
        public void service(ServletRequest req, ServletResponse res)
        throws ServletException, IOException;
        public void destroy();
    
        public ServletConfig getServletConfig();
        public String getServletInfo();
    }
    • Filter接口定義
    public interface Filter{
        public void init(FilterConfig filterConfig) throws ServletException;
    
    }

侷限

  1. 執行完流程(2)後當即Commit ServletResponse, 將響應結果回寫給客戶端.
  2. 侷限(1)致使請求的全部業務邏輯都必須在service()方法內同步執行.
  3. 侷限(2)致使容器的控制線程耗用嚴重, 特別是長鏈接或者阻塞等待(DB,IO,Net)的情景.

看到這裏, 是否是有點明白了!async

Servlet 3.0前, Service容器調用Servlet.service()方法後就會Commit與銷燬ServletResponse, 這致使全部業務邏輯都必須在service()內處理, 無論理是耗時仍是不耗時的, 控制線程必須等待處理完成才能"抽身"服務新的請求.spa

Servlet 3.0 規範提供AsyncContext設施實現ServletResponse的delay commit.線程

AsyncContext原理

經過ServletRequest.startAsync()通知Servlet容器delay ServletResponse的committal, 並返回AsyncContext對象供其餘線程在service()方法結束後使用.code

AsyncContext套路

  1. 設置asyncSupported=true.
    • 在<servlet>或<filter>內使用<async-supported>標籤
    • 在@WebServlet或@WebFilter內使用asyncSupported屬性
  2. 調用ServletRequest.startAsyc()通知容器delay ServletResponse的committal, 並返回AsyncContext對象.
  3. 調用AsycContext.setTimeout()設置超時; 調用AsyncContext.addListener()添加監聽器,設置start/timeout/error/complete的回調方法.
  4. 將AsyncContext對象交給工做線程處理.
    • 自定義線程池: ThreadPoolExecutor
    • 容器線程池: AsyncContext.start()
  5. 控制線程繼續服務其餘請求.
  6. 工做線程完成處理, 響應結果回寫客戶端.
    • 正常完成: 手工調用AsyncContext.complete()
    • 處理超時或發生錯誤, 自動調用AsyncContext.complete().
      只有AsyncContext.complete(), ServletResponse纔會提交, 響應結果纔會回寫客戶端.
    • 分發其餘: 調用dispatch分發其餘Servlet處理.

最佳實踐: 慎重AsyncContext.setTimeout(0)對象

AsyncContext相關的API:

ServletRequest:

  • ServletRequest.isAsyncSupported()
  • ServletRequest.isAsyncStarted()
  • ServletRequest.startAsync(...) #多個
  • ServletRequest.getAsyncContext()

AsyncContext:

可分紅下述幾類接口

  • AsyncContext.getRequest()/getResponse()/hasOriginalRequestAndResponse()
  • AsyncContext.setTimeout()/getTimeout()
  • AsyncContext.addListener(...)/createListener()
  • AsyncContext.complete()/dispatch(...)
  • AsyncContext.start()
相關文章
相關標籤/搜索