1. 程式人生 > >NIO、Servlet3.0、HTTP1.1

NIO、Servlet3.0、HTTP1.1

影響 開始 ann 1.0 star web容器 edt resp style

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,並進行處理.

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

以上的例子可以用於處理對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).

NIO、Servlet3.0、HTTP1.1