應用服務器的web容器一般會爲每一個請求分配一個服務線程。在重負載的場景下,容器須要大量的線程去服務全部客戶端請求。服務可擴展性的限制包括內存不足或者耗盡容器線程。建立可擴展web程序,你必須確保沒有關聯請求的線程是空閒的,因此容器可使用他們處理新請求。
這裏有兩個關聯請求的線程空閒的兩個場景:html
這些場景表明限制web程序可擴展性的阻塞操做。異步處理是指給這些阻塞操做分配一個新線程,並把關聯請求處理的線程返回給web容器。java
java ee支持servlet和filter的異步處理。若是一個servlet或一個filter處理請求時可能到達一個阻塞操做,它能夠把操做分配給一個異步處理上下文而且在不生成響應的狀況下將關聯請求處理的線程回送給web容器。阻塞操做在不一樣線程的異步上下文中執行完成,它能夠生成響應或者轉發請求到另外一個servlet。
在一個servlet上啓用異步處理,設置@WebServlet註解的asyncSupported參數爲true,以下:web
@WebServlet(urlPatterns={"/asyncservlet"}, asyncSupported=true) public class AsyncServlet extends HttpServlet { ... }
javax.servlet.AsyncContext類提供在Service方法中執行異步處理所需的功能。得到一個AsyncContext實例,在service方法中調用request對象的startAsync()方法;例如:數據庫
public void doGet(HttpServletRequest req, HttpServletResponse resp) { ... AsyncContext acontext = req.startAsync(); ... }
這個調用將請求進入異步模式而且確保響應在退出service方法時每個月被提交。你必須在異步上下文完成阻塞操做時生成響應或者轉發到其餘servlet中。
AsyncContext類提供的基礎功能描述:
方法簽名:void start(Runnable run)
描述:容器提供的能提供阻塞操做處理的不一樣線程
方法簽名:ServletRequest getRequest()
描述:返回用來初始化異步上下文的請求。在上面的例子中,request與service方法中的相同。你能夠經過這個方法在異步上下文中從請求中獲取參數。
方法簽名:ServletResponse getResponse()
描述:返回初始化異步上下文的響應。在上面的例子中,response與service方法中的相同。你能夠在異步上下文中,使用這個方法寫入阻塞操做的結果到響應中。
方法簽名:void complete()
描述:完成異步操做,並關閉與此異步上下文關聯的響應。你能夠在異步上下文完成寫入響應後調用這個操做。
方法簽名:void dispatch(String path)
描述:轉發請求和響應到給定的路徑。在阻塞操做完成後,使用這個方法調用另外一個servlet寫出響應。服務器
這個章節示範了怎麼使用AsyncContext上下文提供的功能,有以下用例:併發
下面的例子是一個不使用異步處理的常見servlet:異步
@WebServlet(urlPatterns={"/syncservlet"}) public class SyncServlet extends HttpServlet { private MyRemoteResource resource; @Override public void init(ServletConfig config) { resource = MyRemoteResource.create("config1=x,config2=y"); } @Override public void doGet(HttpServletRequest request, HttpServletResponse response) { response.setContentType("text/html;charset=UTF-8"); String param = request.getParameter("param"); String result = resource.process(param); /* ... print to the response ... */ } }
下面的示例是同一個servlet,但使用了異步處理:async
@WebServlet(urlPatterns={"/asyncservlet"}, asyncSupported=true) public class AsyncServlet extends HttpServlet { /* ... Same variables and init method as in SyncServlet ... */ @Override public void doGet(HttpServletRequest request, HttpServletResponse response) { response.setContentType("text/html;charset=UTF-8"); final AsyncContext acontext = request.startAsync(); acontext.start(new Runnable() { public void run() { String param = acontext.getRequest().getParameter("param"); String result = resource.process(param); HttpServletResponse response = acontext.getResponse(); /* ... print to the response ... */ acontext.complete(); } }
AsyncServlet在@WebServlet註解屬性中添加asyncSupported=true。其他的差別在service方法中:ide
AsyncServlet的service方法當即返回,同時請求在異步上下文中處理。url