thinking in pushlet

介紹

        server端向瀏覽器client發送通知這種通訊模式在J2EE應用中很常見,通常使用採用RMICORBA或者自定義TCP/IP信息的applet來實現。這些技術往往由於複雜而產生諸多不利之處:技術難以實現、存在防火牆限制(因爲需要打開非HTTP的通訊端口)、需要額外的server開發和維護。並且除了刷新整個頁面或者完全採用applet展示內容之外,很難找到別的方法將client端applet的狀態和瀏覽器的頁面內容集成在一起。

        Pushlet是一種comet實現:在Servlet機制下,數據從server端的Java對象直接推送(push)到(動態)HTML頁面,而無需任何Java applet或者插件的幫助。它使server端可以週期性地更新client的web頁面,這與傳統的request/response方式相悖。瀏覽器client爲兼容JavaScript1.4版本以上的瀏覽器(如Internet Explorer、FireFox),並使用JavaScript/Dynamic HTML特性。而低層實現使用一個servlet通過Http連接到JavaScript所在的瀏覽器,並將數據推送到後者。有關JavaScript版本的知識請參看Mozilla開發中心提供的《JavaScript核心參考》Stephen Chapman編寫的《What Version of Javascript》

        這種機制是輕量級的,它使用server端的servlet連接管理、線程工具、javax.servlet API,並通過標準Java特性中Object的wait()和notify()實現的生產者/消費者機制。原則上,Pushlet框架能夠運行在任何支持servlet的server上、防火牆的後面。當在client中使用JavaScript/DHTML時,Pushlet提供了通過腳本快速建立應用、使用HTML/CSS特性集成和佈局新內容的便利方法。

動機

        目前越來越多的servlet和JSP用來部署web,於是便出現了在頁面已經裝載完畢後由於server端某些對象的狀態變化而產生對client瀏覽器進行通知和同步的需要。

        這些狀態變化的原因很複雜:可能由於用戶通過訪問servlet或者修改數據庫記錄、更新EJB造成,或是在多用戶應用(比如聊天室和共享白板)中的事件導致數據狀態變化。這些類型的應用常常使用一種分佈式的MVC模板:模式層位於server上(可能緩存在client中),控制層和視圖層位於client中(這兩個層可能合爲一體)。

        當然,這裏也存在需要訂閱server端動態內容的應用:那些動態內容不停地從server端推送過來。例如股票實時情報、系統狀態報告、天氣情況或者其它的監測應用。它遵循觀察者(Observer)模板(也稱爲發佈/訂閱模板),這種模板中的遠程client註冊成爲關注於server端對象變化的觀察者。關於設計模板的知識請看Matrix Wiki上的介紹

        那麼在HTML頁面已經被裝載後如何通知瀏覽器客戶端?或者如果有選擇地更新頁面中一些部分的話,那該怎麼做?比如只更新在HTML Table中的那些價格發生變化的股票列?

多種通知解決方案

        讓我們對應用進行這樣的假設:擁有一個Java web server或者Java應用server,我們試圖從server發送通知給client端瀏覽器。這裏的解決方案可以分爲:“輪詢(polling)”、“服務端回調(server-side callbacks)”和“消息(messaging)”三類。

輪詢

        最簡單的解決方案便是“定時刷新頁面”。在HTML文檔的頭部使用HTML META標籤,頁面便可以每隔N秒自動reload一次。如果在此期間server端數據發生變化,那麼我們可以獲得新的內容,否則將得到相同的頁面。雖然方法很簡單,但是如何設置刷新間隔是讓人頭疼的大問題。

服務端回調

        因爲我們是“身經百戰”的Java開發老手,所以經常會用到“服務端回調”。這種方式通過RMI或者CORBA將Server端的對象傳輸到Java applet客戶端。

消息(MOM)

        這種解決方案採用一個作爲client的applet,它使用TCP/IP或者無連接的UDP、甚至多播協議來建立與消息中間鍵server的通訊,然後由server推送消息給client。你可以從例如SoftWired的iBusIBM的MQSeriesBEA的WebLogic Event這些消息產品中直接挑選,或者自己使用基於socket的java.io.ObjectStream定製開發消息軟件。

討論(MOM)

        上面三種解決方案在複雜性、安全性、性能、可測量性、瀏覽器兼容性、防火牆限制上各有優勢、劣勢。最佳解決方案依賴於你的應用需求。例如,在共享白板應用中,用戶需要直接與“狀態”交互,那麼server端回調或者消息很可能會大顯身手。

        但在瀏覽器環境下,除非完全使用applet作爲整個client應用,否則把來自於server的更新信息集成到頁面中並非易事。如何在applet收到回調或者消息時變更頁面相關內容?一個很“痛快”而又“痛苦”的解決方案就是在回調方法中使用AppletContext.showDocument(URL)方法來刷新整個頁面。

        由於HTML代碼可以直接影響頁面佈局,直接使用來自server的數據更改HTML部分內容不是更好嗎?這是web應用的理想方案,在server上內容動態改變時,從用戶到server所需的交互是最小化的。作爲對上面的解決方案的補充,我開發了Pushlet這種輕量級、瘦客戶端的技術,它無需applet或者插件而直接與腳本/HTML集成在一起、使用標準HTTP連接、理論上可以部署到任何支持Java servlet的server上。但這並不意味着它將替換對前面解決方案,而是在你的開發“工具箱”中添加另一種選擇。作爲Java構架者/開發者,你可以自行權衡、選擇、決定哪種適合應用的解決方案。

Pushlet原理

        Pushlet的基本使用形式是極爲簡單的。後面的一些示例會說明這一點。

HTTP流

極富生活韻味的“Urban Stream”把我們Connecting Together


        Pushlet基於HTTP流,這種技術常常用在多媒體視頻、通訊應用中,比如QuickTime。與裝載HTTP頁面之後馬上關閉HTTP連接的做法相反,Pushlet採用HTTP流方式將新數據源源不斷地推送到client,再此期間HTTP連接一直保持打開。有關如何在Java中實現這種Keep-alive的長連接請參看Sun提供的《HTTP Persistent Connection》W3C的《HTTP1.1規範》。

示例1

        我們利用HTTP流開發一個JSP頁面(因爲它易於部署,而且它在web server中也是作爲servlet對待的),此頁面在一個定時器循環中不斷地發送新的HTML內容給client:

<% 
  int i = 1;
    
  try {
    while (true) {
       out.print("<h1>"+(i++)+"</h1>");
       out.flush();
      
       try {
            Thread.sleep(3000);
       } catch (InterruptedException e) {
       out.print("<h1>"+e+"</h1>");
        }
     }
   } catch (Exception e) {
       out.print("<h1>"+e+"</h1>");
   }
%>



        在Pushlet源代碼中提供了此頁面(examples/basics/push-html-stream.jsp)。上面的頁面並不是十分有用,因爲在我們刷新頁面時,新內容機械地、持續不斷地被添加到頁面中,而不是server端更新的內容。

示例2

        現在讓我們步入Pushlet工作機理中一探究竟。通過運行Pushlet的示例源代碼(examples/basics/ push-js-stream.html),我們會看到這個每3秒刷新一次的頁面。那麼它是如何實現的呢?

        此示例中包含了三個文件:push-js-stream.html、push-js-stream-pusher.jsp、push-js-stream-display.html。

        其中push-js-stream.html是主框架文件,它以HTML Frame的形式包含其它兩個頁面。

        push-js-stream-pusher.jsp是一個JSP,它執行在server端,此文件內容如下:

   <%
    /** Start a line of JavaScript with a function call to parent frame. */
     String jsFunPre = "<script language=JavaScript >parent.push('";
  
   /** End the line of JavaScript */
   String jsFunPost = "')</script> ";
  
   int i = 1;
   try {
  
     // Every three seconds a line of JavaScript is pushed to the client
     while (true) {
    
        // Push a line of JavaScript to the client
        out.print(jsFunPre+"Page "+(i++)+jsFunPost);
        out.flush();
        
        // Sleep three secs
        try {
             Thread.sleep(3000);
        } catch (InterruptedException e) {
             // Let client display exception
             out.print(jsFunPre+"InterruptedException: "+e+jsFunPost);
        }
      }
    } catch (Exception e) {
             // Let client display exception
             out.print(jsFunPre+"Exception: "+e+jsFunPost);
    }
%>


        注意在示例1和示例2中使用JSP時都存在一個問題:一些servlet引擎在某個client離開時會“吃掉”IOException,以至於JSP頁面將永不拋出此異常。所以在這種情況下,頁面循環將會永遠執行下去。而這正是Pushlet實現採用servlet的原因之一:可以捕獲到IOException。


        在上面代碼的第21行中可以看到在一個定時器循環(3秒/週期)中打印了一些HTML並將它們輸出到client瀏覽器。請注意,這裏推送的並非HTML而是Javascript!這樣做的意義何在?

        它把類似“<script language=JavaScript >parent.push('Page 4')</script>”的一行代碼推送到瀏覽器;而具有JavaScript引擎的瀏覽器可以直接執行收到的每一行代碼,並調用parent.push()函數。而代碼中的Parent便是瀏覽器頁面中所在Frame的Parent,也就是push-js-stream.html。讓我們看看都發生了什麼?

<script LANGUAGE="JavaScript">
var pageStart="<HTML><HEAD></HEAD><BODY BGCOLOR=blue TEXT=white><H2>Server pushes: <para>";
var pageEnd="</H2></BODY></HTML>";
  // Callback function with message from server.
  // This function is called from within the hidden JSP pushlet frame
  function push(content) {
 
    // Refresh the display frame with the content received
    window.frames['displayFrame'].document.writeln(pageStart+content+pageEnd);
    window.frames['displayFrame'].document.close();
  }

</script>



     <!-- frame to display the content pushed by the pushlet -->
     
     
     <!-- Hidden frame with the pushlet that pushes lines of JavaScript-->
     
</FRAMESET>


        可以看到push-js-stream.html中的push()函數被名爲pushletFrame的JSP Frame調用:把傳入的參數值寫入到displayFrame(此Frame爲push-js-stream-display.html)。這是動態HTML的一個小技巧:使用document對象的writeln方法刷新某個Frame或者Window的內容。

        於是displayFrame成爲了用於顯示內容的、真正的視圖。displayFrame初始化爲黑色背景並顯示“wait…”直到來自server的內容被推送過來:

<H1>WAIT...</H1>



        這便是Pushlet的基本做法:我們從servlet(或者從示例中的JSP)把JavaScript代碼作爲HTTP流推送到瀏覽器。這些代碼被瀏覽器的JavaScript引擎解釋並完成一些有趣的工作。於是便輕鬆地完成了從server端的Java到瀏覽器中的JavaScript的回調。

        上面的示例展示了Pushlet原理,但這裏存在一些等待解決的問題和需要增添的特性。於是我建立了一個小型的server端Pushlet框架(其類結構圖表將會展示在下面),添加了一些用在client中的JavaScript庫。由於client需要依賴更多的DHTML特性(比如Layers),我們將首先粗略地溫習一些DHTML知識。示例代碼見examples/dhtml。

DHTML(動態HTML)

        DHTML(動態HTML)提供了在瀏覽器中維護內容、進行用戶交互的擴展能力。就像Java開發者使用servlet和JSP那樣,DHTML也應該是你的工具箱中的一部分。

        DHTML涉及到HTML、級聯樣式表(CSS)、JavaScript和DOM。傳統的頁面只能通過重新裝載來自server新頁面的方式進行更新。DHTML提供了在頁面被裝載完畢後對瀏覽器內的HTML文檔的完全控制。你應該見過一些帶有“圖像翻滾”、彈出內容、可收縮菜單功能的web頁面,它們便是使用DHTML技術實現的。儘管存在一些標準上的差異(見下面的“跨瀏覽器DHTML”),多數兼容JavaScript1.4版本的瀏覽器(後面將簡稱爲“版本4的瀏覽器”)都支持DHTML。

        從開發者的角度審視瀏覽器中的整個文檔,比如Frame、圖片、表格等,它們都可以表示爲具有層次的對象模式——DOM。通過使用JavaScript可以維護DOM的成員,不但可以改變文檔的內容和外觀,而且還可以捕捉例如鼠標移動、form提交這些用戶事件,而後對DOM進行相應修改。例如鼠標移動到圖片的上方可以產生“mouse-over”事件,這時通過顯示高亮版本的圖片或者彈出解釋性文字的方式修改頁面外觀。這聽起來不錯吧!我們現在就熟悉一下DHTML標準!但是誰定義了DHTML標準?

        這是一些DHTML初學者首先遇到的問題。首先,你需要一個版本4以上的瀏覽器。DHTML相關規範的官方標準出自World Wide Web Consortium (W3)。但是微軟和Netscape出品的版本4以上的瀏覽器都有一些私有的DHTML擴展,這是你必須注意的。
幸運的是大多數用戶都有版本4以上的瀏覽器,而且一些開發者(DannymenDan SteinmanDanny Goodman)建造了跨越瀏覽器的、可重用的DHTML庫。

        作爲一名Java開發者,你要接受這個事實:你應該適當地明白基於對象、甚至面向對象的JavaScript編程。在我的DHTML中你將找到一些示例,但瞭解更多的DHTML資源也是很值得的。尤其在使用跨越瀏覽器的DHTML庫對付那些頑固的瀏覽器問題時,一切都變得有趣、而不是枯燥。

        就如Java獲得在廣闊的server端市場、DHTML在client領域具有許多強大特性那樣,Pushlet以一種直接的方式將這兩項偉大的技術捆綁在一起。下一個章節將詳細討論Pushlet這個server端輕量級框架和client端DHTML庫。

框架的設計

        注意:本章節僅反映了Pushlet server端框架的1.0版本(隨着版本升級可能還會重新構造)。

        Pushlet框架允許client訂閱在server端的主題(subject),而server則接收訂閱,然後在server端的訂閱主題所對應的數據變化時推送數據到client。此框架的基本設計模板是發佈/訂閱(Publish/Subscrib),也被稱爲觀察者(Observer)。它具有server和client兩部分組建而成:

        Server端:
        由圍繞着Pushlet類的Java類集合構成(見下面的UML類設計圖表)。

        Client端:
        腳本與頁面:可重用的JavaScript庫(pushlet.js)和用來在DHTML client(這裏指瀏覽器)中接收事件的HTML(pushlet.html)組成。

        Client端Java類:
        JavaPushletClient.java和JavaPushletClientListener.java,負責在Java client中接收事件。

        跨越瀏覽器的DHTML工具庫:
        layer.js, layer-grid.js, layer-region.js,用來在DHTML層中顯示數據內容。

        最後,還有用於測試事件的生成工具類EventGenerators.java以及一些示例應用。

server端類設計

        下面是server端Java類的UML圖表:



Pushlet框架Java類UML圖



        關鍵的類:Pushlet、Publisher類、Subscriber接口和Event類。通過HTTP請求調用Pushlet這個servlet,client訂閱事件並接收事件。

        Client發送訂閱請求時需要表明的內容如下:
        1.訂閱事件的主題
        2.接收事件所採用的格式:默認爲JavaScript調用,還有XML或者Java序列化對象者三種。目前Pushlet 2.0.2版已經支持AJAX。
        3.使用哪種接收協議(將來實現):TCP/IP、UDP、Multicast。

        示例:用於接收AEX股票價格的請求,默認使用JavaScript調用作爲格式。

http://www.fluidiom.com:8080/servlet/pushlet?subject="/stocks/aex"



        主題(subject)表示爲具有層次的“主題樹”(topic-tree)形式。例如:“/stocks”表示與股票價格相關的所有事件,而“/stocks/aex”表示Amsterdam Exchange公司的股票價格。“/”表示所有事件。這並不時硬性規定,而是由開發者根據應用自行定義。

        當前只有接收方協議是發送到client的HTTP迴應流(response stream)。在將來的擴展版本中,接收方協議能夠提供多種選擇,比如TCP、UDP、RMI、HTTP POST甚至只SMTP。

        Event(事件)類:僅僅是name/value的字符串對(使用java.util.Properties實現)的集合。

        產生Event的方式:Publisher類爲生成的Event提供了發佈接口,它內部保存了訂閱者(那些實現Subscriber接口的類)列表,並把每個Event發送給那些主題與Event匹配的訂閱者。Event在server端也可以通過能夠偵聽外部Event的EventGenerators類來生成。另外client可以通過基於HTTP通訊的Postlet類來發布Event。

        在上面的圖表中,爲了適配不同請求源(瀏覽器、Java client程序),PushletSubscriber以及它所包含的那些類提供了多種訂閱者的實現。

場景1: 事件訂閱



瀏覽器client訂閱程序圖



        上面的UML程序圖中,瀏覽器client通過Publisher訂閱Event。

        Pushlet作爲servlet,通過doGet/doPost方法被調用。由於多個client可以同時調用同一個Pushlet,所以Pushlet本身不能作爲訂閱者。取而代之的是,它派發所有的訂閱:在每一次調用doGet()/doPost()時,新建PushletSubscriber對象、並使之運行直至事件循環(eventLoop)結束。PushletSubscriber作爲一個實現Subscriber接口的對象,通過join()方法向Publisher類進行註冊的方式將自身添加到Publisher的內部列表。

        面對不同的client類型和協議,PushletSubscriber建立一個相對的ClientAdapter對象,在這個場景中是BrowserPushletAdapter對象。而對於支持Multipart MIME的瀏覽器,將建立MultipartBrowserClientAdapter對象。

        最後的deQueue()調用是一個“等待Event的循環”,deQueue的意思爲入隊。注意此方法將掛起當前線程直到PushletSubscriber的GuardedQueue隊列中存入有效的Event。

場景2: 發送和派發事件



事件發佈程序圖



        上圖顯示了發送一個事件所要經歷的程序。它展現了Event如何被生成、被派發給瀏覽器client。在這個場景中,EventGenerator建立了一個Event對象,並調用Publisher.publish()將其派發到client。Publisher遍歷它內部的訂閱者列表,詢問這個Event是否匹配訂閱標準(目前只是主題匹配)。如果發現與之匹配的訂閱者,則調用該訂閱者的send()方法。

        每個PushletSubscriber對象都有一個GuardedQueue對象,在其中以隊列的形式保存着調用send()方法時傳入的Event。那麼它爲什麼不直接將Event推送給BrowserPushletAdapter呢?最重要的原因是我們期望掛起BrowserPushletAdapter線程,直到GuardedQueue中存在有效的Event,這樣就避免了“忙於等待”或者“輪詢”方式所帶來的負面影響。第二原因是Publisher可以通知多個client,如果在執行同步的send()調用時,某個慢速的client可能會堵塞所有其它正在等待通知的client。這正是我在RMI或者CORBA提供的一組client進行同步回調的示例中所看到的設計缺陷。

        GuardedQueue是個工具類,它使用了讀/寫模板(readers-writers pattern),此模板採取java.lang.Object.wait()/notifyAll()方法實現可被監控的掛起。通過使用讀/寫模板,使GuardedQueue類具有進行對象入隊/出隊(enqueue/dequeue)操作的能力。當隊列爲空時,GuardedQueue調用deQueue()方法時,此時調用線程將被掛起,直到有對象入隊爲止。相反,當隊列已滿時調用enQueue(),線程也將掛起。在BrowserPushletSubscriber獲得出隊的Event對象後,它將調用BrowserPushletAdapter的push()方法,後者將格式化Event爲JavaScript代碼或者XML以及其它格式),並將它發送到瀏覽器。比如Philips股票價格爲123.45的JavaScript代碼格式如下:

<SCRIPT language=JavaScript >parent.push('subject', '/stocks/aex', 'philips', '123.45') </SCRIPT>



Client端框架

        由於這是對於所有瀏覽器client的通用任務,所以Pushlet Client端框架提供了兩個可重用的文件:
pushlet.html和pushlet.js。
        Pushlet.html本身是被附着在一個隱藏的HTML Frame中。這個Frame的parent調用並實現push()方法。

        pushlet.html :被包含在client端的HTML文檔中的Frame中。它可以傳入主題標識和背景顏色兩個參數。而它所做的最重要的工作是下面的push方法:

function push() {
        // 根據傳入的參數建立PushletEvent object
        // push.arguments是來自server的Event數據
        pushletEvent = new PushletEvent(push.arguments)

        // 更新狀態Frame:顯示閃光表示接收數據
        updateStatusFrame();
        
        // parent frame是否準備好接收Event?
        if (!parent.onPush) {
                return;
        }
        
        // 把Event轉發給parent frame指定的處理方法
        parent.onPush(pushletEvent);
}


        Push()函數首先根據傳入的參數建立了一個JavaScript對象——pushletEvent。接着使用updateStatusFrame()顯示閃光,表示我們正在接收Event數據,如果parent frame存在onPush()函數,則將前面建立的PushletEvent對象作爲參數調用parent frame指定的處理方法。

        在pushlet.js 中的PushletEvent類代碼如下:

/* Object to represent nl.justobjects.pushlet.Event in JavaScript. 
   Arguments are an array where args[i] is name and args[i+1] is value 
*/
function PushletEvent(args) {
   // Map存放Name/Value pairs
   this.map = new Map();
   
   // 設置成員方法
   this.getSubject = PushletEventGetSubject
   this.put = PushletEventPut
   this.get = PushletEventGet
   this.toString = PushletEventToString
   this.toTable = PushletEventToTable

   // 將傳入的參數值放入到map中
   for (var i=0; i < args.length; i++) {
     this.put(args[i], args[++i] );
   }
}

// 獲取事件主題
function PushletEventGetSubject() {
  return this.map.get('subject')
}

// 獲取事件屬性
function PushletEventGet(name) {
  return this.map.get(name)
}

// 存放事件屬性
function PushletEventPut(name, value) {
  return this.map.put(name, value)
}

function PushletEventToString() {
  return this.map.toString();
}

// 將map內容轉化爲HTML Table
function PushletEventToTable() {
  return this.map.toTable();
}


        PushletEvent使用了一個我增加的Map JavaScript對象,它類似於java.util.Hashtable。

Pushlet協議

        詳見http://www.pushlets.com/doc/protocol.html

應用

        Pushlet可以開發多種類型的web應用。由於此框架允許client主動更新事件(通過Postlet),所以應用就並不只是被動地推送數據了。每個Pushlet應用都可以根據下面進行分類:

        事件由server發起、還是client發起或者兩者都有可能;狀態是否保持在server、還是在client或者兩者都有可能。

        由於事件不但被做成了對JavaScript有效,而且也是其它腳本化的插件能夠接收實時的事件更新。例如你可以腳本化Macromedia Flash或者VRML應用。

        爲了說明Pushlet應用的範圍,下面提供了一些簡單的demo。

監控

        例如股票、天氣、投票、機場到達系統,這些應用都可以採用Pushlet對實時數據進行監控。

        這是一個實時FX股票/新聞應用:www.rabotreasuryweb.com (IE only). 另一個部署Pushlet的實時股票/新聞應用:www.marketnews.com.

遊戲
        從象棋到描述危機和壟斷者的遊戲。

分佈式MVC

        這涉及到了在用戶接口框架(例如Java Swing和微軟MFC)中常見的設計模板。在分佈式MVC的各種變體中,模式層位於server,而client控制着是視圖層和控制層。Client通過控制進而修改模式,然後模式將通知所有依附的視圖,而視圖將進行自我刷新。

        一些應用具有web前端(front end),其數據存放在server上可被多個用戶更新。比如預訂系統和登記系統。如果一個client完成一次更新,而其它client卻不能馬上見到變化直至刷新頁面。在某些情況下,這是很簡單、可行的解決方案,但同時也存在着用戶需要同步變化的情況。這種情況下,應用可以使用Pushlet簡單地將URL作爲單一事件推送到client,client接收到這個URL後將刷新頁面。

        另外一點值得注意的示例是爭議頗多的EJB。儘管Java client能夠直接和EJB對話(通過RMI或者CORBA),但多數情況下則是由servlet和作爲client前端的JSP來完成。在這種情況下,“通知”工作變得很艱難。使用Pushlet,EJB可以在其狀態發生改變時通知依附於它的web client。

Web表示層

        在放棄使用PowerPonit作Java課程講解工具後,我開發了一個基於XML的內容管理框架。由於在某些情形下,教室沒有“卷軸工”,但是所有的學生人手一臺網絡計算機,所以我開發了這個簡單的應用,它使我能夠同步改變學生和我的頁面內容。

用戶輔助

        這種類型的應用可用於call center、銀行、幫助桌面、電子商務web應用。當你由於問題而撥打call center電話時,代理程序可以使你通過上網的方式瀏覽解決方案、供貨等信息。

        使用EJB作爲後臺和JSP作爲前臺,client可以買/賣外幣。一個“AutoTrader”對象自動提供處理,如果自動處理失敗或者client請求人工處理時,一個“處理干預”將發生,處理者將被通知並提供相應的服務。

社區工具

        這是一種多用戶參加實時會話的應用。我正在計劃擴充Pushlet框架,使其支持多用戶session的特性。目前可以實現簡單的web聊天,我稱之爲WCQ,大家可以在Pushlet源代碼的example中見到它。

比較

        本章節對Pushlet與基於CORBA/RMI的Java applet解決方案進行一下比較。
優勢
        直接與瀏覽器中的DHTML集成。

        標準的HTTP端口和協議:
消息和RMI/CORBA使用非標準端口(相對HTTP標準端口而言),遇到“防火牆”、“禁止回調”、“禁止接收UDP數據”的瀏覽器安全限制時可能無法工作。

        client負載:基於CORBA/RMI的Java applet使client在啓動時更加沉重,並消耗更多的資源。

        無需額外的server:消息和RMI/CORBA需要單獨的server產品。Pushlet理論上可以在任何server引擎上運行,並具備連接管理和多線程能力。

缺點
        跨越瀏覽器的DHTML:
Pushlet需要使用能工作在任何平臺、所有瀏覽器版本的DHTML庫。

        可測量性:當100個以上的client通過Pushlet連接到server時,server上的線程和socket資源都將出現緊張。而解決這一問題的方式就是使用單獨的Pushlet服務器。

        Web server問題:一般的web server往往不是爲長連接而設計的。針對這一問題的解決方案與上面的可測量性相同。

        代理緩存:一些代理服務器可能緩存HTTP數據。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章