服務器推送的實現—基於EventSource

1、服務器推送理解

  首先要知道爲何使用服務器推送,回答這個問題其實就是至關於回答,服務器推送的優勢,能夠從兩個方面來思考:json

1.1 服務器推送的目的

  及時的將客戶端感興趣的數據推送給它。瀏覽器

1.2 不是用服務器推送怎麼來實現需求

  不使用服務端推送,那就只能由客戶端按期對服務器發送請求,來獲取是否有須要的數據。這樣作有幾個缺點:服務器

  • 不能及時的獲取,最大延時時間爲輪詢間隔。
  • 浪費資源,大部分的請求,都不會獲得數據
  • 輪詢間隔短會對服務器形成較大的壓力。

1.3 使用服務器推送能夠帶來什麼好處

  我理解的有兩個好處,一是及時,還有就是消耗資源穩定(消耗一個鏈接數)。及時很好理解,就是服務器知道數據何時發生變化,發生變化的時候就進行推送。而消耗資源穩定,則是由於只有一個鏈接,全部的數據都從這麼鏈接發送。app

1.4 使用服務器推送有哪些侷限性

  固然就是每個客戶端都須要維護一個長鏈接,客戶端數量增多的時候,會對服務器形成較大的壓力。函數

1.5使用服務器推送的場景

  若是知足如下條件,那麼使用它是最好的作法,若不所有知足,則酌情考慮:學習

  • 要求客戶端能及時的感知服務器數據的變化
  • 客戶端的數量能在服務器的承受範圍內

2、服務器推送的實現

  服務器推送的實現有不少種方式,這一篇博客使用EventSource來實現功能。若要實現服務器推送,須要客戶端和服務端同時對其進行支持。spa

2.1 客戶端代碼

  客戶端代碼比較簡單,實現一個回調函數便可:code

new EventSource("longConnection").onmessage = function(event) {
    $scope.$apply(function() {    
        alert(event.data);        
    }); 
};

  回調函數中的event.data就是服務器發送的數據,此時能夠對它進行其它操做。對象

2.2 服務端代碼

  服務端的代碼通常放到一個循環中:blog

response.setContentType("text/event-stream;charset=UTF-8");
response.setHeader("Cache-Control","no-cache");
response.setHeader("Connection","keep-alive");
PrintWriter out=response.getWriter();
while(true){
    out.print("data: " + 傳遞的數據 + "\n\n");
    out.flush();
}

  只要不把鏈接關閉,那麼每一次刷新,都會講數據發送到客戶端,並觸發onmessage方法。

2.3 注意事項

2.3.1 瀏覽器的支持問題

  默認IE是不支持EventSource對象的,解決辦法是引入一個js文件eventsource.min.js,可是也只能支持IE8及以上。

2.3.2 服務器數據問題

  從上面的例子中能夠發現,往客戶端發送數據的代碼是寫在一個死循環中,那麼怎麼才能實現當敏感數據發生變化時,才使其執行呢,可行性辦法有不少,如今提供一個方法,在全局範圍內使用LinkedBlockingQueue對象,當有須要發送的數據時,將數據放到隊列中,而後在循環中調用poll方法便可。

3、EventSource深刻理解

  若是細心的話能夠發現,在服務端代碼中,寫數據的使用使用了以下格式:

out.print("data: " + 傳遞的數據 + "\n\n");
out.flush();

  每次寫完刷新可不用說,重點是寫數據的時候,有一個前綴和後綴,那麼這個是有什麼規定嗎,仍是說與頁面js代碼一一對應便可,答案是有規定的。下面使用F12對長鏈接進行觀察,能夠看到以下內容:

  具體可使用哪些前綴,有id,data,event,retry和空白,然後綴使用兩個換行,實際上這表明着是一個空行,學習過servlet上傳的可能會理解。

  • id:表明本次事件
  • data:表示傳遞的數據
  • event:表明觸發的事件
  • retry:表明斷開重連後再次等待的時間

  通常用法都是在傳遞的數據中使用json,裏面存放須要調用的方法名,調用參數放在後面,這樣就能夠根據不一樣的數據類型進行不一樣的處理。

  一樣的客戶端代碼中使用了onmessage方法,那麼是否只有這一個方法呢,其實還有額外的兩個方法,這兩個方法視狀況使用 :

  • onopen:這個是在鏈接成功後觸發的。
  • onerror:這個是在出現異常的時候出發的。

4、總結

  這個只是服務端推送的一種實現方式,基本能知足要求,還有其餘方式,後面會介紹。

相關文章
相關標籤/搜索