使用非同步Servlet擴充AJAX應用程式--多工用戶端通訊端

來源:互聯網
上載者:User

作為Web應用程式模型的AJAX的出現使伺服器端的面貌發生了巨大的變化。使用者對著Web頁面填寫表單並單擊提交按鈕轉到下一個連結的典型Web使用模式現在正在轉變為更先進的用戶端JavaScript以及功能更豐富的使用者介面,只要對錶單進行操作,比如單擊一個複選框、按下一個鍵或將滑鼠移到一個選項卡上,該使用者介面就會不斷地與伺服器互動。

考慮一下從用戶端傳輸到伺服器的資料量有多大。從可用性的角度來看,使用者在一個薄用戶端瀏覽器上獲得了富使用者介面,無需安裝任何東西。但是,當在伺服器端擴充這些應用程式時就要付出代價了。AJAX應用程式的典型容量規劃數可能會是標準Web應用程式的3到4倍。

有人可能會問:這對WebLogic Server有何影響?每個發送給WebLogic的HTTP請求都要使用一個執行線程。根據AJAX編程的性質以及許多短期的請求會以輪詢的形式不斷髮送的情況,該行為模式可能造成大量用戶端請求不斷衝擊伺服器的局面。多年來,WebLogic都將這一問題考慮在內,並構建了一個相當棒的特性,即FutureResponseServlet。該範型構建於非同步servlet理念的基礎之上。從版本6.1開始,該功能就允許開發人員提供真正非同步來自伺服器的通知,而無需對事件進行用戶端輪訓並在伺服器端使用執行線程。在9.x之前,BEA還不急於公開該類。

如何在現實中利用該類呢?我們來看一個例子。假定業務需求是要構建一個基於Web的應用程式,該應用程式以近乎即時的方式向伺服器發送資料而無需重新整理瀏覽器。這樣的應用程式可以向伺服器提交一個需要花很長時間處理的請求,而仍然能夠接收到關於其狀態的非同步事件並監聽事件。從技術角度來看,這有許多實現方法。其中一種方法就是使用一個與Java Servlet通訊的Java Applet來獲得非同步資訊。這是一種不錯的方法,但是對於使用者來說有些不太方便,因為他們必須下載一個JVM,還要下載一個applet到瀏覽器。此外,還必須維護一個從用戶端到伺服器的持久性通訊端串連,以便接收非同步訊息。設想一下,如果有1000個使用者使用該applet,那麼就有1000個執行線程幾乎是在空等著發送事件通知到用戶端。當然了,還有其它方法,比如從applet或AJAX應用程式構建輪詢機制來定期檢查新資料。而如果不經常接收到資料,那麼輪詢就顯得無用了,而且還浪費了伺服器資源,佔用了執行線程。反之,伺服器可以定期輪詢,將事件傳播回用戶端,並維護通訊端線程,而無需使用持久性執行線程。這非常類似於Java NIO的運行方式。理想情況下,我們都希望構建一個從伺服器“非同步”接收事件通知而無需在伺服器端使用持久性執行線程的應用程式,不管它是一個applet還是一個基於AJAX的薄Web應用程式。

此問題的一種解決方案是建立一個擴充FutureResponseServlet類的servlet。瀏覽器建立了到FutureResponseServlet類的單一串連,並在另一個線程中將它自身註冊為一個監聽程式。只要在伺服器端接收到一個事件,線程就向用戶端通知該事件。伺服器與用戶端保持非同步,無需使用持久性執行線程。該模型可擴充用於多個並發使用者的情況。

本文並不打算介紹如何構建AJAX應用程式。這方面的文章已經有很多了。本文的重點在於討論展示層(比如AJAX、applet或者任何前端應用程式)的非同步處理的重要性。清單1展示了一個例子。

清單1

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
import java.util.Stack;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import weblogic.servlet.FutureResponseServlet;
import weblogic.servlet.FutureServletResponse;
// An AsynchronousServlet that handles HTTP requests from a "separate" thread and
// not the execute thread used to invoke this servlet.
public class AsynchronousServerResponseServlet extends FutureResponseServlet {
  private final Notifier notifier;
  public AsynchronousServerResponseServlet() {
    this.notifier = new Notifier();
    this.notifier.start();
  }
  public void service(HttpServletRequest request, FutureServletResponse response)
    throws IOException, ServletException {
    // push this client's request to a buffer and return immediately.
    // asynchronous processing occurs in the run method of the Notifier Thread
    notifier.poll(request, response);
  }
  class Notifier extends Thread {
    private static Stack clients = new Stack();
    void poll (HttpServletRequest request, FutureServletResponse response) {
      clients.push(new Client(request, response));
    }
    public void run() {
      while (!clients.empty()) {
        Client client = null;
        try
        {
          client = (Client) clients.pop();
          PrintWriter pw = client.response.getWriter();
          for(int j = 0; j < 10; j++) {
            pw.println("Time is:" + new Date() + "
");
            pw.flush();
          }
          pw.close();
        } catch(Throwable t) {
          t.printStackTrace();
        } finally {
          try {
          client.response.send();
          } catch(IOException ioe) {
          ioe.printStackTrace();
          }
        }
      }
    }
  }
  // inner class that holds on to the clients http request and response
  class Client {
    private HttpServletRequest request;
    private FutureServletResponse response;
    private Client(HttpServletRequest request, FutureServletResponse response) {
      this.request = request;
      this.response = response;
    }
  }
}

可以看出,該例子非常簡單。AsynchronousServerResponseServlet類擴充了FutureResponseServlet,並重寫了service方法。只使用一個線程(即Notifier類)來處理所有的用戶端串連響應。對於每個HTTP請求,servlet向Notifier線程註冊通訊端串連,然後返回。非同步事件被交付給用戶端,而持久性通訊端串連被維持。

單個線程可管理多個用戶端串連!

run()方法可用於根據某種訊息選擇條件回調事件到用戶端。該例子只執行了一個伺服器端的push操作,有些過分簡單了。線程池可被用於某些類型的事件處理。

總而言之,在處理長期啟動並執行任務時,FutureResponseServlet是一個好特性,它允許開發人員提高效能,在獨立的線程中處理響應,並將開銷降至最低。在構建非同步應用程式時,該方法支援延展性。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.