JAVA Web Servlet中的异步处理 (1) -- Servlet3.0中的Async支持
JAVA Web Servlet中的異步處理 (1) – Servlet3.0中的Async支持
每個請求來到Web容器,Web容器會為其分配一個線程來專門負責該請求,直到完成處理前,該執行線程都不會被釋放回容器。 執行線程會耗用系統資源,若有些請求需要長時間處理(例如長時間運算、等待某個資源),就會長時間占用執行線程。
若這類的請求很多,許多執行線程都被長時間占用,而在web容器內,可以使用的線程都是有限的,這對于系統就會是個負擔,甚至造成應用程式的性能瓶頸。
基本上一些需長時間處理的請求,通常客戶端也較不在乎請求后要有立即的回應。若可以,讓這類請求先釋放容器分配給該請求的執行線程,讓容器可以有機會將執行線程資源分配給其它的請求,可以減輕系統負擔。
釋放了容器所分配執行線程的請求,其回應將被延后,直到處理完成(例如長時間運算完成、所需資源已獲得)再行對客戶端的回應。
在Servlet 3.0中,提供了AsyncContext,對異步執行的上下文提供支持。在ServletRequest上提供了 startAsync( )方法,用于啟動異步工作線程。而且AsynchContext還提供了Timeout等設置。
你可以透過AsyncContext的getRequest() 、 getResponse()方法取得Request、Response對象,此次對客戶端的響應將暫緩至調用AsyncContext的complete()方法或dispatch()為止,前者表示回應完成,后者表示將響應調派給指定的URL 。
若要能調用ServletRequest的startAsync()使用AsyncContext,則此Servlet 必須能支援非同步處理,如果使用@WebServlet來標注,則可以設定其asyncSupported為true 。 例如:
@WebServlet(urlPatterns = "/some.do", asyncSupported = true ) public class AsyncServlet extends HttpServlet ...如果使用web.xml設定Servlet,則可以設定標簽為true :
... <servlet> <servlet-name>AsyncServlet</servlet-name> <servlet-class>com.pkgname.AsyncServlet</servlet-class> <async-supported>true</async-supported> </servlet> ...如果Servlet將會異步處理,若其前端有過濾器,則過濾器亦需標示其支援異步處理,如果使用@WebFilter ,同樣是可以設定其asyncSupported為true 。 例如:
@WebFilter(urlPatterns = "/some.do", asyncSupported = true ) public class AsyncFilter implements Filter{ ...如果使用web.xml設定過濾器,則可以設定標簽為true :
... <filter> < filter -name>AsyncFilter</ filter -name> < filter -class>com.pkgname.AsyncFilter</ filter -class> <async-supported>true</async-supported> </ filter > ...注意:
使用異步處理方式,web容器的請求處理線程釋放了,可以服務其他的請求處理。但是該Request的處理并沒有結束,在使用AsyncContext的complete或者dispatch完成后,這個request的處理才結束。
注意: 使用瀏覽器訪問,因為各個瀏覽器的http請求超時設置不同,比如我的chrome是30秒。AsyncContext中對應的工作線程的持續時間需要小于瀏覽器的http超時時間。
AsyncListener
AsyncContext還可以設置一個Listener,對4個事件進行處理:
示例:
package com.ss;import java.io.IOException;import javax.servlet.AsyncContext; import javax.servlet.AsyncEvent; import javax.servlet.AsyncListener; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;/*** Servlet implementation class AsyncServletTest*/ @WebServlet(asyncSupported = true, urlPatterns = { "/AsyncTest" }) public class AsyncServletTest extends HttpServlet {String param = "";private static final long serialVersionUID = 1L;/*** @see HttpServlet#HttpServlet()*/public AsyncServletTest() {super();// TODO Auto-generated constructor stub}/*** @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse* response)*/@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {// 1 start asyncfinal AsyncContext ctx = req.startAsync();param = ctx.getRequest().getParameter("seq");System.out.println("getRequest request seq: " + param);// 2 set the timeoutctx.setTimeout(0);// 3 add listenerctx.addListener(new AsyncListener() {@Overridepublic void onTimeout(AsyncEvent arg0) throws IOException {System.out.println("onTimeout...");}@Overridepublic void onStartAsync(AsyncEvent arg0) throws IOException {System.out.println("onStartAsync...");}@Overridepublic void onError(AsyncEvent arg0) throws IOException {System.out.println("onError...");}@Overridepublic void onComplete(AsyncEvent arg0) throws IOException {System.out.println("onComplete...");}});// 4 run a threadctx.start(new Runnable() {@Overridepublic void run() {String seq = ctx.getRequest().getParameter("seq");System.out.println(">>>>>now respone: " + seq);int n = 0;try {// hold until receive exitwhile (!param.equals("exit")) {n++;if (n % 100000000 == 0) {System.out.println(seq + ": ..." + n); // }}ctx.getResponse().getWriter().write(seq+" -- "+n);} catch (IOException e) {e.printStackTrace();}ctx.complete();}});}/*** @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse* response)*/protected void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {// TODO Auto-generated method stubSystem.out.println("doPost...");}} 創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的JAVA Web Servlet中的异步处理 (1) -- Servlet3.0中的Async支持的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: web压力测试之siege
- 下一篇: SRE重要理念之SLA、SLO、SLI