AsyncContext理解
Servlet 3.0(JSR315)定義了Servlet/Filter的異步特性規範.
怎麼理解"異步Servlet/Filter"及其使用情景?api
Servlet3.0之前
流程:
- 容器初始化ServletRequest與ServletResponse對象.
- 容器調用Servlet實例的service(ServletRequest, ServletResponse)執行業務邏輯.
容器Commit ServletResponse, 將響應結果寫回客戶端並關閉鏈接.異步
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();
}
public interface Filter{
public void init(FilterConfig filterConfig) throws ServletException;
}
侷限
- 執行完流程(2)後當即Commit ServletResponse, 將響應結果回寫給客戶端.
- 侷限(1)致使請求的全部業務邏輯都必須在service()方法內同步執行.
- 侷限(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套路
- 設置asyncSupported=true.
- 在<servlet>或<filter>內使用<async-supported>標籤
- 在@WebServlet或@WebFilter內使用asyncSupported屬性
- 調用ServletRequest.startAsyc()通知容器delay ServletResponse的committal, 並返回AsyncContext對象.
- 調用AsycContext.setTimeout()設置超時; 調用AsyncContext.addListener()添加監聽器,設置start/timeout/error/complete的回調方法.
- 將AsyncContext對象交給工做線程處理.
- 自定義線程池: ThreadPoolExecutor
- 容器線程池: AsyncContext.start()
- 控制線程繼續服務其餘請求.
- 工做線程完成處理, 響應結果回寫客戶端.
- 正常完成: 手工調用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()