NIO、Servlet3.0、HTTP1.1
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,並進行處理.
- @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).
NIO、Servlet3.0、HTTP1.1