彗星
彗星,一種繞太陽公轉的中等大小的冰質物體;當靠近太陽時能夠較長時間大量揮發氣體和塵埃的一種小天體。比太陽行星小, 比月球大。Comet是由希臘文演變而來的,意思是“尾巴”或“毛髮”,也有‘長發星’的含義。所以彗星帶著長長的尾巴,也被稱之為:掃帚星或掃把星。“伺服器推”技術
概念
comet 【計】:基於 HTTP 長連線的“伺服器推”技術,是一種新的 Web 套用架構。基於這種架構開發的套用中,伺服器端會主動以異步的方式向客戶端程式推送數據,而不需要客戶端顯式的發出請求。Comet 架構非常適合事件驅動的 Web 套用,以及對互動性和實時性要求很強的套用,如股票交易行情分析、聊天室和 Web 版線上遊戲等。伺服器推送技術(Server Push)是最近Web技術中最熱門的一個流行術語,它的別名叫Comet(彗星)。它是繼AJAX之後又一個倍受追捧的Web技術。伺服器推送技術最近的流行與AJAX有著密切的關係。
隨著Web技術的流行,越來越多的套用從原有的C/S模式轉變為B/S模式,享受著Web技術所帶來的各種優勢(例如跨平台、免客戶端維護、跨越防火牆、擴展性好等)。但是基於瀏覽器的套用,也有它不足的地方。主要在於界面的友好性和互動性。由於瀏覽器中的頁面每次需要全部刷新才能從伺服器端獲得最新的數據或向伺服器傳送數據,這樣產生的延遲所帶來的視覺感受非常糟糕。因此很多的桌面套用為了獲得更友好的界面放棄了Web技術,或者採用瀏覽器的外掛程式技術(ActiveX、Applet、Flash等)。但是瀏覽器外掛程式技術本身又有許多問題,例如跨平台問題和外掛程式版本兼容性問題。
興起
隨著AJAX技術的興起,讓廣大開發人員又一次看到了使用瀏覽器來替代桌面套用的機會,並且這次機會非常大。AJAX將整個頁面的刷新變成頁面局部的刷新,並且數據的傳送是以異步方式進行,這使得網路延遲帶來的視覺差異將會消失。AJAX還利用DHTML和豐富的JavasSript語言來模擬桌面系統的各種事件和回響過程,以及平滑滾動和拖拽的效果。還不止這些,更有一些IT巨頭(Google、Sun、Oracle等)提供了非常豐富的AJAX開發工具,使得開發和調試AJAX套用變得簡單高效,並且開發的AJAX套用還可以跨越各種瀏覽器和作業系統。在這種情況下基於AJAX的Web套用迅速湧起,吞噬著原有桌面系統的份額。聊天工具、郵件閱讀器、部落格編輯器,甚至是Office辦公軟體和文字處理軟體在瀏覽器中都有著美麗的外觀和幾乎可以與桌面系統媲美的互動界面。Google更是提出“有了瀏覽器和Google,就不需要微軟”的口號和策略。在Ajax的世界中,除了傳統的CAD設計軟體和大型遊戲軟體等因為對系統硬體的苛刻需求,還離不開桌面系統以外,似乎其他所有的套用都可以變成Web套用了。但是,在瀏覽器中的AJAX套用中存在一個致命的缺陷無法滿足傳統桌面系統的需求。那就是“伺服器發起的訊息傳遞(Server-Initiated Message Delivery)”。在很多的套用當中,伺服器軟體需要向客戶端主動傳送訊息或信息。因為伺服器掌握著系統的主要資源,能夠最先獲得系統的狀態變化和事件的發生。當這些變化發生的時候,伺服器需要主動地向客戶端實時地傳送訊息。例如股票的變化。在傳統的桌面系統中,這種需求沒有任何問題,因為客戶端和伺服器之間通常存在著持久的連線,這個連線可以雙向傳遞各種數據。而基於HTTP協定的Web套用卻不行。上節中也提到過,在Web世界中,伺服器永遠是被動地傳送數據,前提是客戶端必須先傳送請求。瀏覽器其實並不知道伺服器的信息什麼時候會有改變,為了模擬實時的交流,或者不想錯過某些信息,只能通過輪詢(Polling)技術不斷刷新頁面來獲得最新的數據(見圖18-5)。這種方式不但浪費伺服器的資源,最重要的是每次建立(或關閉)新的HTTP連線都有一定的延遲,這種延遲使得頻繁信息傳遞的套用無法忍受。於是就產生了“伺服器推送技術”。
技術對比
瀏覽器作為 Web 套用的前台,自身的處理功能比較有限。瀏覽器的發展需要客戶端升級軟體,同時由於客戶端瀏覽器軟體的多樣性,在某種意義上,也影響了瀏覽器新技術的推廣。在 Web 套用中,瀏覽器的主要工作是傳送請求、解析伺服器返回的信息以不同的風格顯示。AJAX 是瀏覽器技術發展的成果,通過在瀏覽器端傳送異步請求,提高了單用戶操作的回響性。但 Web 本質上是一個多用戶的系統,對任何用戶來說,可以認為伺服器是另外一個用戶。現有 AJAX 技術的發展並不能解決在一個多用戶的 Web 套用中,將更新的信息實時傳送給客戶端,從而用戶可能在“過時”的信息下進行操作。而 AJAX 的套用又使後台數據更新更加頻繁成為可能。圖 1. 傳統的 Web 套用模型與基於 AJAX 的模型之比較
“伺服器推”是一種很早就存在的技術,以前在實現上主要是通過客戶端的套接口,或是伺服器端的遠程調用。因為瀏覽器技術的發展比較緩慢,沒有為“伺服器推”的實現提供很好的支持,在純瀏覽器的套用中很難有一個完善的方案去實現“伺服器推”並用於商業程式。最近幾年,因為 AJAX 技術的普及,以及把 IFrame 嵌在“htmlfile“的 ActiveX 組件中可以解決 IE 的載入顯示問題,一些受歡迎的套用如 meebo,gmail+gtalk 在實現中使用了這些新技術;同時“伺服器推”在現實套用中確實存在很多需求。因為這些原因,基於純瀏覽器的“伺服器推”技術開始受到較多關注,Alex Russell(Dojo Toolkit 的項目 Lead)稱這種基於 HTTP 長連線、無須在瀏覽器端安裝外掛程式的“伺服器推”技術為“Comet”。目前已經出現了一些成熟的 Comet 套用以及各種開源框架;一些 Web 伺服器如 Jetty 也在為支持大量並發的長連線進行了很多改進。關於 Comet 技術最新的發展狀況請參考關於 Comet 的 wiki。
下面將介紹兩種 Comet 套用的實現模型。
基於 AJAX 的長輪詢(long-polling)方式
如 圖 1 所示,AJAX 的出現使得 JavaScript 可以調用 XMLHttpRequest 對象發出 HTTP 請求,JavaScript 回響處理函式根據伺服器返回的信息對 HTML 頁面的顯示進行更新。使用 AJAX 實現“伺服器推”與傳統的 AJAX 套用不同之處在於:
伺服器端會阻塞請求直到有數據傳遞或逾時才返回。
客戶端 JavaScript 回響處理函式會在處理完伺服器返回的信息後,再次發出請求,重新建立連線。
當客戶端處理接收的數據、重新建立連線時,伺服器端可能有新的數據到達;這些信息會被伺服器端保存直到客戶端重新建立連線,客戶端會一次把當前伺服器端所有的信息取回。
圖 2. 基於長輪詢的伺服器推模型
一些套用及示例如 “Meebo”, “Pushlet Chat” 都採用了這種長輪詢的方式。相對於“輪詢”(poll),這種長輪詢方式也可以稱為“拉”(pull)。因為這種方案基於 AJAX,具有以下一些優點:請求異步發出;無須安裝外掛程式;IE、Mozilla FireFox 都支持 AJAX。
在這種長輪詢方式下,客戶端是在 XMLHttpRequest 的 readystate 為 4(即數據傳輸結束)時調用回調函式,進行信息處理。當 readystate 為 4 時,數據傳輸結束,連線已經關閉。Mozilla Firefox 提供了對 Streaming AJAX 的支持, 即 readystate 為 3 時(數據仍在傳輸中),客戶端可以讀取數據,從而無須關閉連線,就能讀取處理伺服器端返回的信息。IE 在 readystate 為 3 時,不能讀取伺服器返回的數據,目前 IE 不支持基於 Streaming AJAX。
基於 Iframe 及 htmlfile 的流(streaming)方式
iframe 是很早就存在的一種 HTML 標記, 通過在 HTML 頁面里嵌入一個隱蔵幀,然後將這個隱蔵幀的 SRC 屬性設為對一個長連線的請求,伺服器端就能源源不斷地往客戶端輸入數據。
圖 3. 基於流方式的伺服器推模型
上節提到的 AJAX 方案是在 JavaScript 里處理 XMLHttpRequest 從伺服器取回的數據,然後 Javascript 可以很方便的去控制 HTML 頁面的顯示。同樣的思路用在 iframe 方案的客戶端,iframe 伺服器端並不返回直接顯示在頁面的數據,而是返回對客戶端 Javascript 函式的調用,如“”。伺服器端將返回的數據作為客戶端 JavaScript 函式的參數傳遞;客戶端瀏覽器的 Javascript 引擎在收到伺服器返回的 JavaScript 調用時就會去執行代碼。
從 圖 3 可以看到,每次數據傳送不會關閉連線,連線只會在通信出現錯誤時,或是連線重建時關閉(一些防火牆常被設定為丟棄過長的連線, 伺服器端可以設定一個逾時時間, 逾時後通知客戶端重新建立連線,並關閉原來的連線)。
使用 iframe 請求一個長連線有一個很明顯的不足之處:IE、Morzilla Firefox 下端的進度欄都會顯示載入沒有完成,而且 IE 上方的圖示會不停的轉動,表示載入正在進行。Google 的天才們使用一個稱為“htmlfile”的 ActiveX 解決了在 IE 中的載入顯示問題,並將這種方法用到了 gmail+gtalk 產品中。Alex Russell 在 “What else is burried down in the depth's of Google's amazing JavaScript?”文章中介紹了這種方法。Zeitoun 網站提供的 comet-iframe.tar.gz,封裝了一個基於 iframe 和 htmlfile 的 JavaScript comet 對象,支持 IE、Mozilla Firefox 瀏覽器,可以作為參考。