導航:首頁 > IDC知識 > 伺服器推送技術

伺服器推送技術

發布時間:2020-07-21 22:47:30

1、使用第三方推送服務相比自己搭建推送伺服器有哪些優點和缺點?

看自己推送的服務有哪些,

如果你要推送的服務為價格A+1

你自己搭建推送服務為A+2

相對比自己搭建不發算 如果是長期需要推送服務 就可以選擇自己搭建

自己和第三方推送的優勢:

第一第三方比自己早一步建立的人脈和推送渠道
自己剛搭建沒有這些的所以要浪費很多時間和金錢去建立渠道和人脈

第二 第三方推送伺服器相對比自己搭建的推送服務要成熟
對自己剛搭建有很多不懂

2、推送服務是什麼

推送技術的基礎思想是將瀏覽器主動查詢信息改為伺服器主動發送信息。

伺服器發送一批數據,瀏覽器顯示這些數據,同時保證與伺服器的連接。當伺服器需要再次發送一批數據時,瀏覽器顯示數據並保持連接。以後,伺服器仍然可以發送批量數據,瀏覽器繼續顯示數據,依次類推。

客戶端拉曳 (Client Pull)

在客戶端拖曳技術中,伺服器發送一批數據,在HTTP響應或文檔頭標記中插入指令,讓瀏覽器「在5秒內再次裝入這些數據」或「10秒內前往某URL裝入數據」。當指定的時間達到時,客戶端就按照伺服器的指示去做,或者刷新當前數據,或者調入新的數據。

其實push 和 pull 這兩種技術手段非常不同,但目的幾乎一致,都是為了給最終用戶方便的提供最新信息。

在伺服器推送技術中,HTTP 連接一直保持著,直到伺服器知道自己已結束發送數據並發送一個結束信號,或者客戶端中斷連接。而在客戶端拖曳技術中,並不保持HTTP連接,相反,客戶端被告知合時建立新連接,以及建立連接是獲取什麼數據。

在伺服器推送中,奇妙之處在於「multipart/mixed」格式的 MIME,它能夠使一個報文(或HTTP響應)包含許多數據項、在客戶端拖曳中,奇妙之處在於HTTP響應頭標(或等效的HTML元素),它能告知客戶端在指定的延時時間後執行何種動作。

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

客戶端拖曳效率低,因為這必須每次為傳送數據建立新的連接。但是它不必始終保持連接。

在實際情況中,建立HTTP連接通常需要花費相當多的時間,多達一秒甚至更多。因此從性能上考慮,伺服器推送對於最終用戶更有吸引力,特別是對於需要經常更新信息的情況下。

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

如果實現伺服器推送的CGI程序是使用Shell腳本語言編寫的,有時會存在一些問題。例如,客戶端最終用戶中斷連接,Shell程序通常不能注意到,這將使資源毫無用處的浪費掉,解決這一問題的辦法是用Perl或者C來編寫這類CGI程序,以使用戶中斷連接時能夠結束運行。

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

3、請問RSS的推送技術究竟是怎麼回事?

看一看這個吧,朋友看有沒有用.

推送技術的基礎思想是將瀏覽器主動查詢信息改為伺服器主動發送信息。伺服器發送一批數據,瀏覽器顯示這些數據,同時保證與伺服器的連接。當伺服器需要再次發送一批數據時,瀏覽器顯示數據並保持連接。以後,伺服器仍然可以發送批量數據,瀏覽器繼續顯示數據,依次類推。?

客戶端拉曳(Client?Pull)?

在客戶端拖曳技術中,伺服器發送一批數據,在HTTP響應或文檔頭標記中插入指令,讓瀏覽器「在5秒內再次裝入這些數據」或「10秒內前往某URL裝入數據」。當指定的時間達到時,客戶端就按照伺服器的指示去做,或者刷新當前數據,或者調入新的數據。?

其實push?和?pull?這兩種技術手段非常不同,但目的幾乎一致,都是為了給最終用戶方便的提供最新信息。?

在伺服器推送技術中,HTTP?連接一直保持著,直到伺服器知道自己已結束發送數據並發送一個結束信號,或者客戶端中斷連接。而在客戶端拖曳技術中,並不保持HTTP連接,相反,客戶端被告知合時建立新連接,以及建立連接是獲取什麼數據。?

在伺服器推送中,奇妙之處在於「multipart/mixed」格式的MIME,它能夠使一個報文(或HTTP響應)包含許多數據項、在客戶端拖曳中,奇妙之處在於HTTP響應頭標(或等效的HTML元素),它能告知客戶端在指定的延時時間後執行何種動作。?

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

客戶端拖曳效率低,因為這必須每次為傳送數據建立新的連接。但是它不必始終保持連接。?

在實際情況中,建立HTTP連接通常需要花費相當多的時間,多達一秒甚至更多。因此從性能上考慮,伺服器推送對於最終用戶更有吸引力,特別是對於需要經常更新信息的情況下。?

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

如果實現伺服器推送的CGI程序是使用Shell腳本語言編寫的,有時會存在一些問題。例如,客戶端最終用戶中斷連接,Shell程序通常不能注意到,這將使資源毫無用處的浪費掉,解決這一問題的辦法是用Perl或者C來編寫這類CGI程序,以使用戶中斷連接時能夠結束運行。?

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

接下來就大概說說伺服器推送技術?
伺服器在響應請求時,HTTP使用MIME報文格式來封裝數據。通常一個HTTP響應只能包含一個數據塊。但MIME有一種機制可用一個報文(或HTTP響應)表示將多個數據塊,這種機制就是成為「multipart/mixed」的標准MIME類型。multipart/mixed報文大體格式如下:?
Content-type:multipart/mixed;boundary=ThisRandomString?
--ThisRandomString?
Content-type:text/plain?
第一個對象的數據。?
--ThisRandomString?
Content-type:text/plain?
第二個對象的數據。?
--ThisRandomString--?

上述報文包括兩上數據塊,二者的類型都是「text/plain」。最後一個「ThisRandomString」後的兩條短線(--)表示報文結束,後面沒有數據。?

對於伺服器推送,使用一個「multipart/mixed」類型的變種--multipart/x-mixed-replace。這里,「x-」表示屬於實驗類型。「replace」表示每一個新數據塊都會代替前一個數據塊。也就是說,新數據不是附加到舊數據之後,而是替代它。?

下面是實際使用的「multipart/x-mixed-replace」類型:?
Content-type:multipart/x-mixed-replace;boundary=ThisRandomString?
--ThisRandomString?
Content-type:text/plain?
第一個對象的數據?
--ThisRandomString?
Content-type:text/plain?
第二個(最後一個)對象的數據。?
--ThisRandomString--?
使用這一技術的關鍵是,伺服器並不是推送整個「multipart/x-mixed-replace」報文,而是每次發送後數據塊。?
HTTP連接始終保持,因而伺服器可以按自己需要的速度和頻率推送新數據,兩個數據塊之間瀏覽器僅需在當前窗口等候,用戶甚至可以到其他窗口做別的事情,當伺服器需要發送新數據時,它只是源(ABC輸入法沒那個字*&^$#)傳輸管道發送數據塊,客戶端相應的窗口進行自我更新。?

在伺服器推送技術中,「multipart/x-mixed-replace」類型的報文由唯一的邊界線組成,這些邊界線分割每個數據塊。每個數據塊都有自己的頭標,因而能夠指定對象相關的內容類型和其他信息。由於「multipart/x-mixed-replace」的特性是每一新數據塊取代前一數據對象,因而瀏覽器中總是顯示最新的數據對象。?
「multipart/x-mixed-replace」報文沒有結尾。也就是說,伺服器可以永遠保持連接,並發送所需的數據。如果用戶不再在瀏覽器窗口中顯示數據流,或者瀏覽器到伺服器間的連接中間(例如用戶按「STOP」按鈕),伺服器的推送才會中斷。這是人們使用伺服器推送的典型方式。?

當瀏覽器發現「Content-type」頭標或到達頭標結束處時,瀏覽器窗口中的前一個文檔被清除,並開始顯示下一個文檔。發現下一個報文邊界時,就認為當前數據塊(文檔)已經結束。?
總之,伺服器推送的數據由一組頭標(通常包括「Content-type」)、數據本身和分割符(報文邊界)三部分組成。瀏覽器看到分割符時,它保持狀態不變,直到下一個數據塊到達。?

4、html5現在可以實現伺服器推送了嗎

對於某些類型的應用來說,伺服器推送事件是最佳的選擇。本文對伺服器推送技術進行了詳細的介紹,包含瀏覽器端和伺服器端的相應實現細節,為在實踐中使用該技術提供了指南。

對於一般的 Web 應用開發,大多數開發人員並不陌生。在 Web 應用中,瀏覽器和伺服器之間使用的是請求 / 響應的交互模式。瀏覽器發出請求,伺服器根據收到的請求來生成相應的響應。瀏覽器再對收到的響應進行處理,展現給用戶。響應的格式可能是 HTML、XML 或 JSON 等。隨著 REST 架構風格和 AJAX 的流行,伺服器更多地使用 JSON 作為響應的數據格式。Web 應用使用 XMLHttpRequest 對象來發送請求,並根據伺服器端返回的數據,對頁面的內容進行動態更新。通常來說,用戶在頁面上的操作,比如點擊或移動滑鼠,會觸發相應的事件。由 XMLHttpRequest 對象來發出請求,得到伺服器響應之後進行頁面的局部更新。這種方式的不足之處在於:伺服器端產生的數據變化不能及時地通知瀏覽器,而是需要等到下次請求發出時才能被瀏覽器獲取。對於某些對數據實時性要求很高的應用來說,這種延遲是不能接受的。
為了滿足這類應用的需求,就需要有某種方式能夠從伺服器端推送數據給瀏覽器,以保證伺服器端的數據變化可以在第一時間通知給用戶。目前常見的解決辦法有不少,主要可以分成兩類。這兩類方法的區別在於是否基於 HTTP 協議來實現。不使用 HTTP 協議的做法是使用 HTML 5 新增的 WebSocket 規范,而使用 HTTP 協議的做法則包括簡易輪詢、COMET 技術和本文中要介紹的 HTML 5 伺服器推送事件。下面會對這幾種技術進行介紹。
簡介
在介紹 HTML 5 伺服器推送事件之前,首先介紹一些上面提到的幾種伺服器端數據推送技術。第一種是 WebSocket。WebSocket 規范是 HTML 5 中的一個重要組成部分,已經被很多主流瀏覽器所支持,也有不少基於 WebSocket 開發的應用。正如名稱所表示的一樣,WebSocket 使用的是套接字連接,基於 TCP 協議。使用 WebSocket 之後,實際上在伺服器端和瀏覽器之間建立一個套接字連接,可以進行雙向的數據傳輸。WebSocket 的功能是很強大的,使用起來也靈活,可以適用於不同的場景。不過 WebSocket 技術也比較復雜,包括伺服器端和瀏覽器端的實現都不同於一般的 Web 應用。
除了 WebSocket 之外,其他的實現方式是基於 HTTP 協議來達到實時推送的效果。第一種做法是簡易輪詢,即瀏覽器端定時向伺服器端發出請求,來查詢是否有數據更新。這種做法比較簡單,可以在一定程度上解決問題。不過對於輪詢的時間間隔需要進行仔細考慮。輪詢的間隔過長,會導致用戶不能及時接收到更新的數據;輪詢的間隔過短,會導致查詢請求過多,增加伺服器端的負擔。
COMET 技術改進了簡易輪詢的缺點,使用的是長輪詢。長輪詢的方式在每次請求時,伺服器端會保持該連接在一段時間內處於打開狀態,而不是在響應完成之後就立即關閉。這樣做的好處是在連接處於打開狀態的時間段內,伺服器端產生的數據更新可以被及時地返回給瀏覽器。當上一個長連接關閉之後,瀏覽器會立即打開一個新的長連接來繼續請求。不過 COMET 技術的實現在伺服器端和瀏覽器端都需要第三方庫的支持。
綜合比較上面提到的 4 種不同的技術,簡易輪詢由於其本身的缺陷,並不推薦使用。COMET 技術並不是 HTML 5 標準的一部分,從兼容標準的角度出發,也不推薦使用。WebSocket 規范和伺服器推送技術都是 HTML 5 標準的組成部分,在主流瀏覽器上都提供了原生的支持,是推薦使用的。不過 WebSocket 規范更加復雜一些,適用於需要進行復雜雙向數據通訊的場景。對於簡單的伺服器數據推送的場景,使用伺服器推送事件就足夠了。
在瀏覽器支持方面,伺服器推送事件已經在除 IE 外的大部分桌面和移動瀏覽器上得到了支持。支持伺服器推送事件的瀏覽器及其版本包括:Firefox 6.0+、Chrome 6.0+、Safari 5.0+、Opera 11.0+、iOS Safari 4.0+、Opera Mobile 11.1+、Chrome for Android 25.0+、Firefox for Android 19.0+ 以及 Blackberry Browser 7.0+ 等。關於 IE 的支持,在下面的章節中有詳細的介紹。
下面對伺服器推送事件的規范進行具體的說明。
規范
Server-sent Events 規范是 HTML 5 規范的一個組成部分,具體的規範文檔見參考資源。該規范比較簡單,主要由兩個部分組成:第一個部分是伺服器端與瀏覽器端之間的通訊協議,第二部分則是在瀏覽器端可供 JavaScript 使用的 EventSource 對象。通訊協議是基於純文本的簡單協議。伺服器端的響應的內容類型是「text/event-stream」。響應文本的內容可以看成是一個事件流,由不同的事件所組成。每個事件由類型和數據兩部分組成,同時每個事件可以有一個可選的標識符。不同事件的內容之間通過僅包含回車符和換行符的空行(「\r\n」)來分隔。每個事件的數據可能由多行組成。代碼清單 1 給出了伺服器端響應的示例。
清單 1. 伺服器端響應的示例
data: first event

data: second event
id: 100

event: myevent
data: third event
id: 101

: this is a comment
data: fourth event
data: fourth event continue

如代碼清單 1 所示,每個事件之間通過空行來分隔。對於每一行來說,冒號(「:」)前面表示的是該行的類型,冒號後面則是對應的值。可能的類型包括:
類型為空白,表示該行是注釋,會在處理時被忽略。
類型為 data,表示該行包含的是數據。以 data 開頭的行可以出現多次。所有這些行都是該事件的數據。
類型為 event,表示該行用來聲明事件的類型。瀏覽器在收到數據時,會產生對應類型的事件。
類型為 id,表示該行用來聲明事件的標識符。
類型為 retry,表示該行用來聲明瀏覽器在連接斷開之後進行再次連接之前的等待時間。
在代碼清單 1 中,第一個事件只包含數據「first event」,會產生默認的事件;第二個事件的標識符是 100,數據為「second event」;第三個事件會產生類型為「myevent」的事件;最後一個事件的數據為「fourth event\nfourth event continue」。當有多行數據時,實際的數據由每行數據以換行符連接而成。
如果伺服器端返回的數據中包含了事件的標識符,瀏覽器會記錄最近一次接收到的事件的標識符。如果與伺服器端的連接中斷,當瀏覽器端再次進行連接時,會通過 HTTP 頭「Last-Event-ID」來聲明最後一次接收到的事件的標識符。伺服器端可以通過瀏覽器端發送的事件標識符來確定從哪個事件開始來繼續連接。
對於伺服器端返回的響應,瀏覽器端需要在 JavaScript 中使用 EventSource 對象來進行處理。EventSource 使用的是標準的事件監聽器方式,只需要在對象上添加相應的事件處理方法即可。EventSource 提供了三個標准事件,如表 1 所示。
表 1. EventSource 對象提供的標准事件

名稱
說明
事件處理方法

open 當成功與伺服器建立連接時產生 onopen
message 當收到伺服器發送的事件時產生 onmessage
error 當出現錯誤時產生 onerror
如之前所述,伺服器端可以返回自定義類型的事件。對於這些事件,可以使用 addEventListener 方法來添加相應的事件處理方法。代碼清單 2 給出了 EventSource 對象的使用示例。
清單 2. EventSource 對象的使用示例
var es = new EventSource('events');
es.onmessage = function(e) {
console.log(e.data);
};

es.addEventListener('myevent', function(e) {
console.log(e.data);
});

如代碼清單 2 所示,在指定 URL 創建出 EventSource 對象之後,可以通過 onmessage 和 addEventListener 方法來添加事件處理方法。當伺服器端有新的事件產生,相應的事件處理方法會被調用。EventSource 對象的 onmessage 屬性的作用類似於 addEventListener( 『 message 』 ),不過 onmessage 屬性只支持一個事件處理方法。
在介紹完伺服器推送事件的規范內容之後,下面介紹伺服器端的實現。

5、php如何實現伺服器推送技術,即時把信的數據發送到客戶端。

主要有三種方案
第一種是利用第三方的API來實現信息推送,主要包括環信、百度雲推送、leancloud等
第二種通過javascript的setTimeout或者setInterval來實現,同理PHP端也可以用守護進程來實現
第三種通過Linux的計劃任務來實時推送需要消息

6、推送技術的評價標准

推送方案的公認評價採取4s標准:1.Safe(安全) 2. Stable(穩定) 3.Save(省電省流量省成本) 4.Slim(體積小) 推送方案應支持透傳及各種加密方案,保障信息傳遞安全。
推送方案的ID系統應該獨立於已有的網站或服務的ID系統,這樣保障用戶在不同手機上登錄後的信息投遞准確性,避免因為取消綁定事件失敗因網路傳輸而造成的信息誤投送。 穩定包括兩個部分一個是伺服器端的穩定性,一個是手機端的穩定性。
服務端穩定性,因為使用長連接方案,對伺服器的開銷和要求很大,推送方案對伺服器開發要求很高,海量線程連接下的伺服器穩定性是非常具有挑戰性的。一般的評判標准包括:
- 同時在線時峰值 (一般按照百萬並發連接時伺服器穩定性評測)
- 高並發時消息平均延遲時間(一般按照1分鍾處理1百萬條信息評測)
- 服務穩定性 (一般要求全年99.9%以上可用,有備份,有負載均衡等)
鑒於伺服器穩定的開發難度很大,小團隊不建議自己開發,建議使用穩定的第三方推送方案,如個推,蝴蝶等。
手機端的穩定性,主要是因為中國的復雜網路狀況及手機型號適配情況造成手機長時間穩定聯網較困難,所以穩定性非常重要,一般的評判標准包括:
- 每日聯網23.5小時以上用戶比例 (表徵聯網穩定性)
- 消息發送後9小時內收到率 (表徵到達率)
一般來說,推送方案要做網路的分運營商,分省,分機型適配,自己開發工作量較大
3.Save(節省)
省電應注意CPU休眠,一般用服務縮短待機時間百分比評判
省流量應注意協議的修改和冗餘數據包的處理,一般用空載待機月流量評判
省成本應考慮單伺服器承載同時連接數,可承載同時連接數越多成本越低,業內 頂尖水平為個推的單伺服器50萬連接
4.Slim(體積小)
推送服務應該體積盡量小,不影響主程序的大小和復雜度,一般以小於300K為宜。

7、推送機制和後台的區別?

像wp7和IOS都有一個系統級的消息服務,這個消息服務是和伺服器保持了一下長連接,然後伺服器有信息可以隨時發給你。這個消息中包含了消息的內容,歸屬,也就是這條消息是屬於誰的。這個消息服務的是整個系統。
後台的話就是自助餐,你都是自己去伺服器取,看看盤子里有沒有食物。有的話就端回來。沒有就一個勁兒去看。這個比較耗資源。流量和電量等。

基本上是可以這樣理解的。說的也不是特別的好。

8、數據實時推送怎麼實現

Ajax 技術已經存在了一段時間,開發的動力已經真正開始得到了人們的認可。越來越多的 Web 站點正在考慮使用Ajax 進行設計,開發人員也開始將 Ajax 的能力發揮到極限。隨著社交網路和協作式報告等現象的出現,一組全新的要求浮現出來。如果有其他用戶更改了某位用戶正在觀察的任何活動,則用戶希望得到通知。如果一個 Web 站點顯示動態數據,如股價等,那麼所有用戶都必須立即得到關於變更的通知。
這些場景本身屬於一類稱為 「伺服器推送」 的問題。通常,伺服器是中心實體,伺服器將首先獲得關於所發生的任何更改的通知,伺服器負責將此類更改通知所有連接的客戶端。但遺憾的是,HTTP 是客戶端-伺服器通信的標准協議,它是無狀態的,而且在某種意義上來說,也是一種單向的協議。HTTP 場景中的所有通信都必須由客戶端發起,至伺服器結束,然而我們所提到的場景的需求則完全相反。對於伺服器推送來說,需要由伺服器發起通信,並向客戶端發送數據。HTTP 協議並無相關配置,Web 站點應用程序開發人員使用獨創的方法來繞過這些問題,例如輪詢,客戶端會以固定(或可配置)的時間間隔與伺服器聯系,查找是否有新更新可用。在大多數時候,這些輪詢純粹是浪費,因而伺服器沒有任何更新。這種方法不是沒有代價的,它有兩大主要問題。
這種方法極度浪費網路資源。每一個輪詢請求通常都會創建一個 TCP 套接字連接(除非 HTTP 1.1 將自己的keepAlive 設置為 true,此時將使用之前創建的套接字)。套接字連接本身代價極高。除此之外,每一次請求都要在網路上傳輸一些數據,如果請求未在伺服器上發現任何更新,那麼這樣的數據傳輸就是浪費資源。如果在客戶端機器上還運行著其他應用程序,那麼這些輪詢會減少傳輸數據可用的帶寬。
即便是請求成功,確實為客戶端傳回了更新,考慮到輪詢的頻率,這樣的更新也不是實時的。例如,假設輪詢配置為每 20 秒一次,就在一次請求剛剛從伺服器返回時,發生了更新。那麼這次更新將在 20 秒後的下一次請求到來時才能返回客戶端。因而,伺服器上准備好供客戶端使用的更新必須等待一段時間,才能真正地為客戶端所用。對於需要以盡可能實時的方式運行的應用程序來說,這樣的等待是不可接受的。
考慮到這樣兩個問題,對於需要關鍵、實時的伺服器端更新的企業應用程序而言,輪詢並不是最理想的方法。在這篇文章中,我將介紹多種可以替代輪詢的方法。每一種替代方法在某些場景中都有自己的突出之處。我將說明這些場景,並展示需要實時伺服器推送的一組 UI。
Ajax 應用程序中的伺服器更新技術
讓我們來具體看看用於更新來自伺服器的信息的一些常用技術,這些技術模擬了伺服器推送。
短輪詢
短輪詢也稱為高頻輪詢,就是我在本文開頭處介紹的技術。這種方法在以下情況中表現最好:
有足夠的帶寬可用。
根據統計數據,大多數時候,請求都能獲得更新。例如,股市數據就總是有可用更新。
使用 HTTP 1.1 協議。設置 keepAlive=true,因而,同一個套接字連接始終保持活動狀態,並可重用。
長輪詢
長輪詢是用於更新伺服器數據的另外一種方法。這種方法的理念就是客戶端建立連接,伺服器阻塞連接(通過使請求線程在某些條件下處於等待狀態),有數據可用時,伺服器將通過阻塞的連接發送數據,隨後關閉連接。客戶端在接收到更新後,立即重新建立連接,伺服器重復上述過程,以此實現近於實時的通信。然而,長輪詢具有以下缺陷:
一般的瀏覽器默認允許每台伺服器具有兩個連接。在這種情況下,一個連接始終是繁忙狀態。因而,UI 只有一個連接(也就是說,能力減半)可用於為用戶請求提供服務。這可能會導致某些操作的性能降低。
仍然需要打開和關閉 HTTP 連接,如果採用的是非持久連接模式(keepAlive=false),那麼這種方法的代價可能極高。
這種方法近於實時,但並非真正的實時。(當然,某些外部因素總是不可控的,比如網路延時,在任何方法中都會存在這些因素。)
流通道
流通道(streaming channel)與長輪詢大致相同,差別在於伺服器不會關閉響應流。而是特意保持其處於打開狀態,使瀏覽器認為還有更多數據即將到來。但是,流通道也有著自己的缺陷:
最大的問題就是數據刷新(flushing)。過去,Web 伺服器會緩存響應數據,僅在接受到足夠的位元組數或塊數後才會發送出去。在這種情況下,即便應用程序刷新數據,也仍然會由伺服器緩存,以實現優化。更糟的是,如果在客戶端和伺服器之間存在代理伺服器,那麼代理也可能會為自身之便緩存數據。
如果發現套接字將打開較長的時間,某些瀏覽器實現可能會自行決定關閉套接字。在這種情況下,通道需要重新建立。
通常,第一個問題可通過為每個流響應附加垃圾有效載荷來解決,使響應數據足以填滿緩沖區。第二個問題可通過「保持活動」 或按固定間隔 「同步」 消息來欺瞞瀏覽器,使瀏覽器認為數據是以較慢的速率傳入的。
這些解決方案適用的用例范圍狹窄。所有這些方法都已經在 Internet 上的某些解決方案中得到了應用。然而,這些解決方案都遭遇了相同的問題:缺乏可伸縮性。典型情況下,要阻塞一個請求,需要阻塞處理請求的線程,因為如今幾乎所有應用伺服器都會執行阻塞 I/O。即便不是這樣,Java™ 2 Platform, Enterprise Edition (J2EE) 也未提供為 HTTP 請求和響應執行非阻塞 I/O 的標准。(Servlets 3.0 API 可解決這一問題,因為這些 API 中包含Comet Servlet。)
至此,需要具備非阻塞 I/O(NIO)伺服器,客戶端應用程序通過它進行連接。由於此類套接字是純 TCP 二進制套接字,因而將實現以下目標:
由於伺服器端具有 NIO,因而可實現更高的可伸縮性。
響應緩存的問題不復存在,因為這個套接字直接受應用程序的控制。
基於上述說明,有必要指出這種方法的四個缺點:
由於使用的是二進制 TCP 套接字,因而應用程序無法真正地利用 HTTPS 層提供的 SSL 安全性。所以,要求數據安全性的應用程序可能需要提供自己的加密工具。
通常情況下,伺服器套接字將在 80 以外的埠上運行,如果防火牆僅允許來自埠 80 的流量,將出現問題。因而,可能需要進行一些埠配置。
Ajax 客戶端無法通過後端打開 TCP 套接字連接。
即便 Ajax 客戶端能夠執行 open 函數,也無法理解二進制內容,這是因為 Ajax 使用的是 XML 或 JSON(基於文本)格式。
在這篇文章中,要強調的是如何真正地繞開第三個和第四個問題。如果能夠處理安全性和防火牆問題,那麼其他問題也能得到處理。這種做法的獲益極為顯著。
可為應用程序實現最大程度的實時伺服器推送行為(不考慮網路延時等外部因素),將獲得高度可伸縮的解決方案(以同時連接的客戶端數量為准)。
下面解決上述的第三個和第四個問題。
基於套接字的 RIA 技術
Ajax 並不能真正地解決第三個和第四個問題。因而,需要利用其他 RIA 技術尋求解決方案。有兩種 RIA 技術提供的套接字 API 可與 Ajax 應用程序交互。這兩種技術是 Adobe Flex 和 OpenLaszlo。全面介紹這兩種技術並非本文討論范圍之內,但這些技術提供的兩種特性如下所示:
均能通過後端打開 TCP 二進制套接字
均能出色地與運行在同一個瀏覽器窗口中的 Ajax 應用程序(主要是 JavaScript)交互
但這僅僅解決了部分問題。確實可以打開套接字,可以使 Ajax 應用程序使用它們,但 Ajax 應用程序仍然無法處理純二進制數據。實際上,這兩種技術都提供了二進制 TCP 套接字的一種變體,稱為XMLSocket,它可用於來回傳輸純 XML 數據。這正是您需要的東西。如果這些技術能夠通過伺服器打開套接字,如果它們能夠傳輸 XML 數據,任務就完成了。Ajax 應用程序可充分利用這一點,模擬實時伺服器推送技術。下面將介紹如何實現。
實現 Ajax 伺服器推送
將使用兩種工具解釋這項技術:Adobe Flex 和 OpenLaszlo。首先,需要編寫能夠接收並緩存連接的後端伺服器。在這里不能太過偏離主題,因而要保證伺服器基於阻塞 I/O。
需要創建一個伺服器套接字,接收預先指定地址的連接:
清單 1. 創建伺服器套接字
public class SimpleServer {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket();
serverSocket.bind(new InetSocketAddress("localhost",20340));
Socket socket = serverSocket.accept();
}
}
在這里,將伺服器套接字綁定到 localhost:20340 這一地址。當一個客戶端連接到該伺服器套接字時,它將為我提供一個套接字,顯示連接。Flex 客戶端隨後會要求策略文件,這是其安全性模型的一部分。通常,這個策略文件的形式類似於清單 2。
清單 2. Flex 客戶端策略文件
<?xml version="1.0"?>
<!DOCTYPE cross-domain-policy SYSTEM
"http://www.adobe.com/xml/dtds/cross-domain-policy.dtd">
<cross-domain-policy>
<allow-access-from domain="*" to-ports="20340"/>
</cross-domain-policy>
就在連接之後,Flex 客戶端會立即發送一條策略文件的請求。該請求僅包含一個 XML 標記:<policy-file-request/>。在響應中,您需要返回此策略文件。清單 3 中的代碼就完成了這個任務。
清單 3. 發送策略文件響應
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket();
serverSocket.bind(new InetSocketAddress("localhost", 20340));
Socket socket = serverSocket.accept();
String POLICY_REQUEST = "<policy-file-request/>\u0000";
String POLICY_FILE = "<?xml version=\"1.0\"?>\n" +
"<!DOCTYPE cross-domain-policy SYSTEM
\"http://www.adobe.com/xml/dtds/cross-domain-policy.dtd\">\n" +
"<cross-domain-policy> \n" +
" <allow-access-from domain=\"*\" to-ports=\"20340\"/> \n" +
"</cross-domain-policy>";
byte[] b = new byte[POLICY_REQUEST.length()];
DataInputStream dataInputStream = new DataInputStream(socket.getInputStream());
dataInputStream.readFully(b);
String request = new String(b);
if (POLICY_REQUEST.equals(request)) {
DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream());
dataOutputStream.write(POLICY_FILE.getBytes());
dataOutputStream.flush();
dataOutputStream.close();
} else throw new IllegalArgumentException("unknown request format " + request);
}
此代碼建立了與客戶端的成功連接。現在,伺服器可以與客戶端發起 「握手」 之類的協議,此時,伺服器通常會指定一個惟一的 ID,並將其發送給客戶端,此後,伺服器可根據 ID 緩存套接字,在此之後,如果伺服器需要向客戶端推送某些數據,可以按照 ID 定位套接字,並使用其輸出流。幸運的是,OpenLaszlo 也使用了相同的基於策略文件的機制,因而,同樣的伺服器代碼適用於兩種場景。
下面將介紹如何創建 Flex 套接字,隨後將其與 Ajax 應用程序連接。
使用 Adobe Flex 打開客戶端套接字
清單 4 中的代碼展示了如何通過 Flex 打開客戶端套接字:
清單 4. 通過 Flex 打開客戶端
var socket : XMLSocket = new XMLSocket();
// register events:
socket.addEventListener(Event.CLOSE, closehandler);
socket.addEventListener(Event.CONNECT, connectHandler);
socket.addEventListener(Event.OPEN, openHandler);
socket.addEventListener(ProgressEvent.SOCKET_DATA, readHandler);
socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
socket.connect("localhost",20340);
完成 socket.connect() 調用後,Flex 將向伺服器發送一條請求,要求提供策略文件,期待獲得 XML 響應。完成之後,連接即建立,這個套接字現在即可用於從伺服器推送數據。
作為拼圖的最後一塊,將看到 Flex 如何將 Ajax 作為應用程序調用。為此,要編寫一個可處理伺服器端消息的通用 JavaScript 函數。將此方法命名為 handleServerMessageReceived(message)。此方法會獲取來自伺服器的 XML 代碼,此方法對於消息的處理方式以應用程序為依據。清單 5 中的代碼展示了 Flex 如何調用 JavaScript函數。這是 readHandler 方法的代碼,該方法在接收到伺服器 XML 消息時被調用。
清單 5. 使用 handleServerMessageReceived(message) 的 readhHandler 代碼
public function readHandler(e : DataEvent) : void {
var message: XML = e.data as XML;
ExternalInterface.call("handleServerMessageReceived", message);
}
就是這樣!就是這樣簡單。已經創建了一個 XML 套接字連接。當來自伺服器的數據送達時,可調用 Ajax 中的某些通用處理函數,處理這些消息。完整源代碼可供下載(請參見下載部分)。
下面來看看 OpenLaszlo 如何實現相同的目標。
使用 OpenLaszlo 打開客戶端套接字
由於 OpenLaszlo 應用程序以 Flash 和 DHTML 平台為目標,因而其 API 和腳本語言類似於 Flash 和JavaScript。這主要是為希望遷移到 OpenLaszlo(作為 RIA 的替代方案)的 Web 開發人員提供便利。
OpenLaszlo 提供了兩種創建與後端之間的持久連接的方法。一種方法要使用 Lz(Laszlo 的縮寫)標准庫中提供的ConnectionManager API。但其文檔明確說明了以下內容:
「警告:這項特性是臨時的。此特性用於容量有限的環境,能夠用於開發,但我們不推薦使用此特性進行部署(不包括低容量、非任務關鍵型的部署)。若對使用此版本的持久連接的應用程序的健壯性有任何問題,請直接咨詢Laszlo Systems。」
或許目前這是一項實驗技術,但在未來的 OpenLaszlo 版本中,它將得到證實。
第二種方法與 Flex 相似,您要手動打開 XML 套接字連接,等待 READ_DATA 事件發生。清單 6 展示了實現方法。
清單 6. 定義 XMLSocket 類
<class name="ClientSocket" extends="node">
<attribute name="host" />
<attribute name="port" />
<XMLSocket name='xml_socket'/>
<handler name="oninit">
// connect the socket here:
xml_socket.connect(host,port);
</handler>
<handler name='onData' reference='xml_socket' args='messageXML'>
<![CDATA[
ExternalInterface.call(『handleServerMessageReceived',messageXML);
]]>
</method>
</class>
(為簡短起見,忽略了其他處理方法。在本文的下載部分中可獲得完整的代碼清單。)
就是這樣,創建一個套接字對象並連接此對象就是這樣輕松。這一代碼清單創建了一個名為 ClientSocket 的新類,隨後聲明了一個名為 「xml_socket」 的 XML 套接字對象。只要此套接字對象讀取到來自伺服器的數據,就會觸發onData 事件,該事件將由為 onData 定義的處理方法處理。最後,在 onData 處理方法中,調用 Ajax 應用程序中的外部 JavaScript 函數。此後的流程與 Flex 客戶端相同。
要創建 ClientSocket 對象,只需聲明它即可:
清單 7. 聲明 ClientSocket
<canvas>
<ClientSocket id='serverPushSocket' host='localhost' port='20340'/>
</canvas>
為 ClientSocket 觸發了 init 事件時,將嘗試連接指定主機和埠的後端。(請參見清單 6 中的 oninit 處理方法。)
結束語
這篇文章討論了幾種模擬伺服器推送的方法,從純輪詢到實時伺服器推送,文中說明了每種方法的優缺點。最後,重點關注了能夠提供最優伺服器可伸縮性和實時伺服器推送行為的方法。
伺服器推送並非適用於每一個應用程序。實際上,大多數應用程序都非常適合普通的請求/響應場景。其他一些應用程序使用輪詢和類似的技術足以滿足需求。只有那些伺服器更新極為重要、客戶端需要得到即時通知的重量級應用程序才需要本文所述技術。有必要再次強調,這種技術有兩個主要的缺點:
如果數據需要通過 HTTPS 傳輸,客戶端套接字無法利用 SSL 加密工具。
防火牆需要允許客戶端套接字通過非標准埠(非 80 埠)連接到伺服器。
然而,市面上存在著大量開源庫,可利用它們輕松編寫自定義的加密常式。類似地,配置防火牆也是輕而易舉的,實際上,只需付出很少的代價,即可獲得強大的實時伺服器推送功能。

9、推送技術的一般應用

推送服務通常是在事先表達喜好的信息。這就是所謂的發布/訂閱模型。一個客戶端可能「訂閱」的各種信息「通道」。每當新的內容可以在這些渠道之一,伺服器會推出的信息給用戶。
同步會議和即時消息是推動服務的典型例子。郵件和聊天,有時文件推到了只要他們是由信息服務受到了用戶。同行都分散的對等程序(如廢物),並集中程序(如IRC或XMPP協議)允許推送文件,這意味著發送者發起數據傳輸,而不是接受者。
電郵也是一個推動系統:SMTP協議的基礎上,它是一個推動協議(見PushMail)。不過,最後一步,從郵件伺服器到桌面計算機通常使用的POP3或IMAP像拉協議。現代電子郵件客戶端走這一步似乎瞬間通過反復投票的郵件伺服器,經常檢查新郵件了。 IMAP協議包括IDLE命令,它允許伺服器告訴客戶端新郵件到達時。原來的黑莓是第一推技術流行的例子了在無線方面的電子郵件。
另一種普及型互聯網推送技術為pointcast公司網路,該網路在1990年代獲得了知名度。它傳遞新聞和股市數據。 Netscape和微軟自己的軟體集成到它在瀏覽器大戰的高度,但後來逐漸消失,並在與RSS(一拉技術)2000年代取代。
其他用途的Web應用,包括推動市場數據發布(股票行情),在線聊天/消息系統(網上聊天),拍賣,網上博彩和游戲,運動的結果,監測主機和感測器網路監控。

與伺服器推送技術相關的知識