服務器推送技術

1        背景

“服務器推送技術”( Server Pushing )是最近 Web 技術中最熱門的一個流行術語。它是繼“ Ajax ”之後又一個倍受追捧的 Web 技術。“服務器推送技術”最近的流行跟“ Ajax ”有着密切的關係。

隨着 Ajax 技術的興起,讓廣大開發人員又一次看到了使用瀏覽器來替代桌面應用的機會,並且這次機會非常大。 Ajax 將整個頁面的刷新變成頁面局部的刷新,並且數據的傳送是以異步方式進行,這使得網絡延遲帶來的視覺差異將會消失。

但是,在瀏覽器中的 Ajax 應用中存在一個致命的缺陷無法滿足傳統桌面系統的需求。那就是“服務器發起的消息傳遞”( Server-Initiated Message Delivery )。 在很多的應用當中,服務器軟件需要向客戶端主動發送消息或信息。因爲服務器掌握着系統的主要資源,能夠最先獲得系統的狀態變化和事件的發生。當這些變化發 生的時候,服務器需要主動的向客戶端實時的發送消息。例如股票的變化。在傳統的桌面系統這種需求沒有任何問題,因爲客戶端和服務器之間通常存在着持久的連 接,這個連接可以雙向傳遞各種數據。而基於 HTTP 協議的 Web 應用卻不行。

2        客戶端得到通知的方式

 

1 傳統web 訪問機制

我們知道, Web 的訪問機制天生是設計用來 pull 數據的,如圖 1 ,也就是隻允許 Browser 端主動發起請求, server 是被動的響應,不允許 Server Browser 發出一個 connection 請求,也就是說沒有爲 server Browser push 數據提供設計實現 . 雖然沒有直接的實現方法 , 卻可以使用一些變通的方式完成類似的功能。

2.1    傳統輪詢

Web 早期,這一點常使用 meta 刷新實現。這將自動指示瀏覽器在指定秒數之後重新裝載頁面,從而支持簡陋的輪詢( polling )。例如在 HTML 文件中加入 <META HTTP-RQUIV="Refresh" CONTENT=12> ,實際上就是 HTTP 頭標告知瀏覽器每 12 秒更新一次文檔。

優點 :不需要服務器端的配置。

缺點

a)          糟糕的用戶體驗

b)         對服務器的壓力很大,並且造成帶寬的極大浪費。

2.2    Ajax 輪詢

Ajax 隔一段時間(通常使用 JavaScript setTimeout 函數)就去服務器查詢是否有改變,從而進行增量式的更新。但是間隔多長時間去查詢成了問題,因爲性能和即時性造成了嚴重的反比關係。間隔太短,連續不斷的請求會沖垮服務器,間隔太長,務器上的新數據就需要越多的時間才能到達客戶機。

優點:

a)          不需要太多服務器端的配置。

b)         降低帶寬的負荷(因爲服務器返回的不是完整頁面)。

缺點:

a)          對服務器的壓力並不會有明顯的減少。

b)         實時性差,有一定的延遲。

應用: 這是一項非常常見的技術,例如,大多數 webmail 應用程序就是通過這種技術在電子郵件到達時顯示電子郵件的。

2.3    Comet

Comet 方式通俗的說就是一種長連接機制 (long lived http) 。同樣是由 Browser 端主動發起請求,但是 Server 端以一種似乎非常慢的響應方式給出回答。這樣在這個期間內,服務器端可以使用同一個 connection 把要更新的數據主動發送給 Browser 。因此請求可能等待較長的時間,期間沒有任何數據返回,但是一旦有了新的數據,它將立即被髮送到客戶機。 Comet 又有很多種實現方式,但是總的來說對 Server 端的負載都會有增加 . 雖然對於單位操作來說,每次只需要建議一次 connection, 但是由於 connection 是保持較長時間的 , 對於 server 端的資源的佔用要有所增加。

優點: 實時性好(消息延時小);性能好(能支持大量用戶)

缺點: 長期佔用連接,喪失了無狀態高併發的特點。

應用: 股票系統、實時通訊。

2.4    Flash XML Socket

這種方案實現的基礎是:一、 Flash 提供了 XMLSocket 類。二、 JavaScript Flash 的緊密結合:在 JavaScript 可以直接調用 Flash 程序提供的接口。

缺點:

a)          因爲 XMLSocket 沒有 HTTP 隧道功能, XMLSocket 類不能自動穿過防火牆;

b)         因爲是使用套接口,需要設置一個通信端口,防火牆、代理服務器也可能對非 HTTP 通道端口進行限制;

應用: 網絡聊天室,網絡互動遊戲。

2.5    Java Applet 套接口

在客戶端使用 Java Applet ,通過 java.net.Socket java.net.DatagramSocket java.net.MulticastSocket 建立與服務器端的套接口連接,從而實現 服務器推送

缺點: 需要客戶端安裝 JAVA 虛擬機。

3        Comet 介紹

Comet 有時也稱反向 Ajax 或服務器端推技術( server-side push )。其思想很簡單:將數據直接從服務器推到瀏覽器,而不必等到瀏覽器請求數據。聽起來簡單,但是如果熟悉 Web 應用程序,尤其是 HTTP 協議,那麼您就會知道,這絕不簡單。實現 Comet 風格的 Web 應用程序,同時保證在瀏覽器和服務器上的可伸縮性,這只是在最近幾年才成爲可能。目前一些主流網站都有類似的原理,例如: webQQ 、開心網、校內等等,它們中消息動態都是採用類似的技術,只是具體實現方式不一樣。

COMET 的精髓就在於用服務器與 javascript 來維持瀏覽器的長連接,同時完成服務器端事件的瀏覽器端響應。這樣的事件廣播機制是跨網絡的,同時也是實時的。

採用了 Comet 技術的 服務器 在客戶機做出一個請求後,和客戶機建立一個永久的連接,然後 服務器 會根據客戶機的請求不斷把數據包推向客戶,這個推的過程是不間斷的。由 服務器 推向客戶機的數據在客戶機的瀏覽器上會不斷產生新的內容,而且不會產生 Client pull 那樣的 HTML 文檔頭,從而大大減少了延遲的時間,向( 服務器 響應 -- 客戶機請求)同步邁進了一步。

服務器推送通常效率要比客戶端拖曳效率高,因爲它不必爲後續數據建立新的連接。由於始終保持連接,即使沒有數據傳輸時也是這樣,因此服務器必須願意分配這些 TCP/IP 端口,對於 TCP/IP 端口數有限的服務器這將是一個嚴重的問題。

客戶端拖曳效率低,因爲這必須每次爲傳送數據建立新的連接。但是它不必始終保持連接。在實際情況中,建立 HTTP 連接通常需要花費相當多的時間,多達一秒甚至更多。因此從性能上考慮,服務器推送對於最終用戶更有吸引力,特別是對於需要經常更新信息的情況下。

服 務器推送相對客戶端拖曳的另一點優勢是,服務器推送相對比較容易控制。例如,服務器每一次推送時都保持一個連接,但它又隨時可以關閉其中的任何連接,而不 需要在服務器上設置特殊的算法。而客戶端拖曳在同樣的情況下要麻煩許多,它每次要與服務器建立連接,服務器爲了處理將客戶端拖曳請求與特定的最終用戶匹配 等情況,需要使用相當麻煩的算法。

如上所述,在服務器推送中,多個響應中連接始終保持,使服務器可在任何時間發送更多的數據。一個明顯的好處是服務器完全能夠控制更新數據的時間和頻率。另外,這種方法效率高,因爲始終保持連接。缺點是保持連接狀態會浪費服務器端的資源。服務器推送還比較容易中斷。

4        Comet 實現( Java 語言)

4.1    死循環法

最簡單的自然是死循環法,如果使用觀察者模式則可以進一步提高性能。

但是這種做法的缺點在於客戶端請求了這個 servlet 後, web 服務器會開啓一個線程執行 servlet 的代碼,而 servlet 由遲遲不肯結束,造成該線程也無法被釋放。於是乎,一個客戶端一個線程,當客戶端數量增加時,服務器依然會承受很大的負擔。

4.2       改寫 web 服務器

目前的趨勢是從 web 服務器內部入手,用 nio JDK 1.4 提出的 java.nio 包)改寫 request/response 的實現,再利用線程池增強服務器的資源利用率,從而解決這個問題,目前支持這一非 J2EE 官方技術的服務器有 Glassfish Jetty

JDK 1.4 版本 ( 包括之後的版本 ) 最顯著的新特性就是增加了 NIO(New IO) ,能夠以非阻塞的方式處理網絡的請求,這就使得在 Java 中只需要少量的線程就能處理大量的併發請求了。

Jetty 6 設計來處理大量併發連接,它使用 Java 語言的不堵塞 I/O(java.nio) 庫並且使用優化的輸出緩衝架構。 Jetty 也有一個處理長連接的殺手鐗 : 一個稱爲 Continuations 的特性。

Grizzly 作爲 GlassFish 中非常重要的一個項目,就是用 NIO 的技術來實現應用服務器中的高性能純 Java HTTP 引擎。 Grizzly 還是一個獨立於 GlassFish 的框架結構,可以單獨用來擴展和構建自己的服務器軟件。

特點: 使用 NIO 不是一件簡單的技術,它的一些特點使得編程的模型比原來阻塞的方式更爲複雜。

4.3    使用框架

基於 Java 的成熟的服務器推送框架有 DWR

DWR 是一個開放源碼的使用 Apache 許可協議的解決方案,它包含服務器端 Java 庫、一個 DWR servlet 以及 JavaScript 庫。雖然 DWR 不是 Java 平臺上唯一可用的 Ajax-RPC 工具包,但是它是最成熟的,而且提供了許多有用的功能。從最簡單的角度來說, DWR 是一個引擎,可以把服務器端 Java 對象的方法公開給 JavaScript 代碼。使用 DWR 可以有效地從應用程序代碼中把 Ajax 的全部請求 - 響應循環消除掉。這意味着客戶端代碼再也不需要直接處理 XMLHttpRequest 對象或者服務器的響應。不再需要編寫對象的序列化代碼或者使用第三方工具才能把對象變成 XML 。甚至不再需要編寫 servlet 代碼把 Ajax 請求調整成對 Java 域對象的調用。

DWR 2.0 開始增加了 push 功能 , 也就是在異步傳輸的情況下可以從 Web-Server 端發送數據到 Browser

特點: 技術成熟,配置簡單, DWR Spring Struts2 Ext JS 都能整合。

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