HTML5資料推送SSE原理及應用開發

floraLam的部落格發表於2015-03-21

JavaScript表達行為,CSS表達外觀,注意HTML既表達結構(邏輯結構),又表達內容(資料本身)通常需要更新資料時,並不需要更新結構,正是這種不改變組織結構僅改變資料的訴求,推動了資料拉取和資料推送技術的產生。

SSE是一種允許伺服器端向客戶端推送新資料(簡稱資料推送)的HTML5技術。資料推送有兩種替代方案:無更新方案和資料拉取方案。

無更新方案:

載入完畢HTML之後,得到一個HTML頁面,之後瀏覽器會請求圖片、CSS檔案和JavaScript檔案等,他們都是瀏覽器可以快取的靜態檔案。如果頁面使用後端語言,比如PHP、Ruby和Python等為使用者動態生成HTML的語言。

資料拉取方案:

瀏覽器會基於一些使用者行為,或在一定時間之後,或基於某種別的觸發方案,向伺服器端請求或全部更新資料,通過javascript或一個meta標籤能夠命令整個頁面重新載入。我們所熟悉的Ajax技術只被用於請求最新資料,當收到資料時,javascript函式會利用它來區域性更新DOM。資料拉取的要義:僅拉取新資料,並且只更新頁面中受影響部分。

以上的都不是資料推送,資料推送不是靜態檔案,也不涉及瀏覽器為更新資料而發起請求,資料推送是由伺服器選擇客戶端傳送新資料。

當資料來源有新資料時,伺服器端能立刻傳送給一個或多個客戶端,而不用等客戶端來請求,這些新資料可能是突發新聞、最新股票、上線朋友的聊天資訊、新的天氣預報、策略遊戲中的下一步等。

SSE適用於更新頻繁、低延遲並且資料都是從服務端到客戶端。它和WebSocket的區別:

1)便利,不需要新增任何新元件,用任何習慣的後端語言和框架就能繼續使用,不用為新建虛擬機器弄一個新的IP或新的埠號而勞神。

2)伺服器端的簡潔。因為SSE能在現有的HTTP/HTTPS協議上運作,所以它能夠直接執行於現有的代理伺服器和認證技術。

WebSocket相較SSE最大的優勢在於它是雙向交流的,這意味著伺服器傳送資料就像從伺服器接受資料一樣簡單,而SSE一般通過一個獨立的Ajax請求從客戶端向服務端傳送資料,因此相對於WebSocket使用Ajax會增加開銷。因此,如果需要以每秒一次或者更快的頻率向服務端傳輸資料,就應該用WebSocket。

具體程式碼如下:

html程式碼

<!doctype html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>basic SSE test</title>
    </head>
    <body>
        <pre id = "x">initializting...</pre>
        <!--之所以使用pre標籤而不是p或者div是為了確保資料能以它被接受時的格式呈現,而不會修改或格式化-->

    </body>
    <script>
        var es = new EventSource("basic_sse.php");
        es.addEventListener("message",function(e){
            //e.data
            document.getElementById("x").innerHTML += "\n"+e.data;
        },false);//使用false表示在冒泡階段處理事件,而不是捕獲階段。
    </script>
</html>

需要注意的是:使用伺服器端資料之前最好做一下檢查,以防潛在的javascript注入攻擊。

php程式碼

<?php
    header('Content-Type: text/event-stream');
    header('Cache-Control: no-cache');
    $time = date('r');
    echo "data: The server time is: {$time}\n\n";
    flush();
?>

“Content-Type: text/event-stream”是專門為SSE設計的MIME型別,

效果截圖

什麼時候資料推送是錯誤的選擇

首先考慮靜態的情況,不引入資料推送,每當使用者開啟一個頁面,在瀏覽器和伺服器之間就會開啟i一個套接字連線,伺服器手機資訊然後返回給使用者,可能很簡單,就像從磁碟上載入一個靜態的HTML檔案或一張圖片一樣,也可能很複雜,就像要執行一段用以連線很多資料庫的後臺語言。這裡的關鍵點就是,一旦返回了所需的資訊,套接字就會關閉,每個HTTP請求都會開啟一個這種生命週期相對較短的套接字連線,這些套接字是伺服器上有限的資源,每當它們完成既定任務,就會被回收以迴圈再利用。

現在對比看一下資料推送。一個請求永遠不會完成,總是有很多資訊要傳送,所以套接字會一直保持開啟狀態。顯然,因為它們是有限的資源,所以同一時刻的SSE連線數會有限制。

想象一種情況,你在為你最新的應用提供電話服務支援,有10個接線中心員工為1000個使用者提供服務,使用者遇到問題,其中一個接線員接線,然後掛線。新的客戶呼叫在排隊,知道其中一個接線員掛線,這是典型的網路服務模式。

但是,現在有個客戶打過來說,我現在沒有問題,但是接下來幾個小時都會用到你們的產品,並且如果遇到問題,我希望你們立即回覆。這個客戶將與接線員保持通話幾個小時,那麼呼叫中心的10%服務資源就被浪費。如果有10個這樣的客戶,那麼其他990個客戶就無法呼叫。這就是資料推送模式。

當然,這並不總是壞事,如果這個客戶一下午每隔幾秒鐘就有一個問題,這種情況保持電話通暢不但沒有浪費10%服務資源,反而會增加。因為每個問題都需要新打一個電話(就像資料拉取),接線員需要花額外的時間,驗證客戶身份,調出賬戶,降低服務效率。保持電話通常不僅使得客戶更滿意,也會提高呼叫中心的工作效率,這就是資料推送的最適合場景。

相關文章