当前位置: 代码迷 >> Web前端 >> Servlet3.0新功能: 异步处置
  详细解决方案

Servlet3.0新功能: 异步处置

热度:363   发布时间:2012-11-01 11:11:31.0
Servlet3.0新功能: 异步处理

J2EE 6和Glassfish 3V正式发布了,J2EE 6正式发布了Servlet3.0, 为了能更好的对WEB2.0提供支持, 3 .0添加了异步处理的机制.

?

HTTP1.1相对于HTTP1.0的影响 .

?

HTTP1.1最大的一个改变就是提供了长连接,这样HTTP不再是一次请求,一次连接的协议了,只要HTTP的connection不关闭,一次 HTTP连接可以支持任意多次request/reponse处理. 当WEB Client与WEB Server建立连接时,客户端可以采用长连接,也就是说Client会一直保持对WEB Server的连接(例如:Browser对一个网站保持当连接,知道Browser关闭或最终退出该网站). 旧的WEB Server会为每一个Http连接分配一个active的Thread,这样当Client的数量增大时,Server端Thread Pool的最大容量也需要相应增大,但Thread是相当耗内存的,一个不小心就会导致Server端NotEnoughMemory...

?

基于HTTP1.1,大部分支持Servlet2.X的WEB容器都采用的NIO去接收和处理请求. 当Client和Server端建立连接时,Server端并不分配一个Thread给HTTP连接.直到Server端收到Client端发送的 Request时, Server才开始为该Request分配Thread(注意:这里不是为HTTP连接分配Thread ).

?

这样当大量的Client建立长连接与Server进行交互时,Server无需维持一个Thread给inactive的HTTP长连接, 每个Servlet 在doReceived()时其实对应的是一个active Request,而不是HTTPConnection本身. 这样Server端所需的最大Thread数大大地减少了.

?

AJAX的影响

?

1. Request的数量爆炸性增加增加

?

过去WEB Browser打开一个Web page,只需要和Web Server端建立一个HTTP连接.但AJAX技术出现以后,一个Web page上可能有多个与Web Server的连接,而且Ajax request通常是十分频繁的,Server接收到的Request数量大大增长了, 这样原先NIO的技术已经不能很好的支持基于Ajax的服务了.

?

Servlet 3 .0的异步处理就能够解决上面的问题.

?

Servlet3.0的solution:

当request发送到Server端时,servlet 的doReceived() 将request放进一个queue里,然后doReceived结束.这个时候server并没有关闭response,Client端一直在等 server端response的内容. Server端维护自己的ThreadPool,当ThreadPool里有idle的Thread,就从queue里取出一个request,分配 idle的Thread给request,并进行处理.

?

Java代码
  1. ??? @WebServlet ( "/test" ?asyncSupported= true )??
  2. ???public ? class ?MyServlet? extends ?HttpServlet?{??
  3. ???????ScheduledThreadPoolExecutor?executor?=?null ;??
  4. ??
  5. ????????public ? void ?init(ServletConfig?arg0)? throws ?ServletException?{??
  6. ???????????????????executor?=?new ?ThreadPoolExecutor( 10 ); //独立的线程池处理请求 ??
  7. ????????}??
  8. ????????public ? void ?doGet(HttpServletRequest?req,?HttpServletResponse?res)?{??
  9. ????????????...??
  10. ????????????AsyncContext?aCtx?=?request.startAsync(req,?res);??
  11. ????????????executor.execute(new ?AsyncWebService(aCtx)); //异步处理 ??
  12. ????????}??
  13. ???}??
  14. ??
  15. ???public ? class ?AsyncWebService? implements ?Runnable?{??
  16. ????????AsyncContext?ctx;??
  17. ????????public ?AsyncWebService(AsyncContext?ctx)?{??
  18. ????????????this .ctx?=?ctx;??
  19. ????????}??
  20. ????????public ? void ?run()?{ //处理请求 ??
  21. ????????????//Do?something?here?... ??
  22. ??
  23. ????????????//?Dispatch?the?request?to?render?the?result?to?a?JSP. ??
  24. ????????????ctx.dispatch("/render.jsp" );??
  25. ???}??
  26. }??
   @WebServlet("/test" asyncSupported=true)   public class MyServlet extends HttpServlet {       ScheduledThreadPoolExecutor executor = null;        public void init(ServletConfig arg0) throws ServletException {                   executor = new ThreadPoolExecutor(10);//独立的线程池处理请求        }        public void doGet(HttpServletRequest req, HttpServletResponse res) {            ...            AsyncContext aCtx = request.startAsync(req, res);            executor.execute(new AsyncWebService(aCtx));//异步处理        }   }   public class AsyncWebService implements Runnable {        AsyncContext ctx;        public AsyncWebService(AsyncContext ctx) {            this.ctx = ctx;        }        public void run() {//处理请求            //Do something here ...            // Dispatch the request to render the result to a JSP.            ctx.dispatch("/render.jsp");   }}

?以上的例子可以用于处理对Ajax的请求,因为通常Ajax的请求多,但对响应速度的要求并不太高. 对于正常的页面请求,要求一定的响应速度,可以沿用以前Servlet 同步的实现.

?

2. Server端推送信息

在Web2.0的应用中, Ajax可用通过不断的发送Request来获取Server端某种信息的变化,但这种实现会产生大量的Client请求. 当前推荐的方法是,让Server端自己推送信息变化给Client.

?

因为Servlet3.0提供了异步处理的方式, Request提交给Server以后, Server可以为Request注册一个Listener,由Listener去monitor信息的变化,当信息发生变化时,由Listener负责 把信息变化发送给Cient(Listener关闭HTTP response).