聶永的博客

          記錄工作/學習的點點滴滴。

          Servlet 3.0筆記之異步請求Comet流推送(Streaming)實現小結

          Servlet3規范支持異步請求(或者稱為長連接,或者反向AJAX,或者COMET,或者服務器推送技術):無阻塞的輸入與輸出模型,可以延時的請求和響應功能,還有超時事件通知,看上去一切都是那么完美。
          但終端瀏覽器支持長連接情況差強人意,對Comet的支持大致匯總如下:
          1. IE瀏覽器最佳實踐是使用htmlfile ActiveXObject,以及創建隱藏IFrame組件,可以跨越IE6-IE8;雖IE 8支持XDomainRequest支持HTTP Streaming,但僅僅是IE 8。
          2. Firefox 瀏覽器相當棒,支持XMLHttpRequest Streaming 和隱藏的IFrame組件。
          3. Safari 瀏覽器支持XMLHttpRequest Streaming。
          4. Chrome有些無奈,算不上支持XMLHttpRequest Streaming,使用IFrame的話會一直出現正在加載中的標志。
          5. Opera也不支持XMLHttpRequest Streaming,使用IFrame的話會一直出現正在加載中的標志。
          總之,使用IFrame是一個不錯的方案,在IE、Firefox下表現的很完美,在其它瀏覽器下只能忍受討厭的正在加載中。數據交換格式可以采用JS腳本調用。
          但無論哪一種方案,都必須認識到,一個持久的連接,當頁面內容一直在遞增時,會越來越膨脹,會占用用戶機器的CPU,盡量隔一段時間斷開連接,重新請求。
          HTTP 1.1規范中聲明客戶端不應該與服務器端建立超過兩個 HTTP 連接,因此瀏覽器內需要借助腳本避免客戶重開兩個腳本。
          按照目前情形下,需要借助AJAX PULL  + COMET PUSH 相結合來打造相當好的用戶體驗。
          Servlet本身,無論2.4或者2.5的版本,可以使用一個循環達到長連接的目標:
          /**
          * 一個典型的長連接實現
          *
          * @author yongboy
          * @date 2011-1-14
          * @version 1.0
          */
          @WebServlet("/demoLongLink")
          public class DemoLongLinkServlet extends HttpServlet {
          private static final long serialVersionUID = 4617227991063927036L;

          protected void doGet(HttpServletRequest request,
          HttpServletResponse response) throws ServletException, IOException {

          response.setHeader("Cache-Control", "private");
          response.setHeader("Pragma", "no-cache");
          response.setHeader("Connection", "Keep-Alive");
          response.setHeader("Proxy-Connection", "Keep-Alive");
          response.setContentType("text/html;charset=UTF-8");

          PrintWriter out = response.getWriter();
          out.println("<div>Start ...</div>");
          out.flush();

          int num = 0;
          int max = 100;
          while (true) {
          out.println("<div>" + (num++) + "</div>");
          out.flush();

          if (num >= max) {
          break;
          }

          try {
          Thread.sleep(1000);
          } catch (InterruptedException e) {
          e.printStackTrace();
          }
          }

          out.println("<div>Done !</div>");
          out.flush();
          out.close();
          }
          }
          每一個連接線程都處于一個不斷循環之中,不能夠有效釋放,相當的浪費服務器資源,有可能導致容器內線程池耗盡,將無法應對后續請求。同時少了異步連接的特性,無法直接定義超時時間,更不要說超時事件,超時監聽器等企業特性了。
          當然也可以實現異步請求,但可能沒有規范那般嚴格。
          同步請求的模型:
          對比異步請求模型:
          上面兩張圖借用了涂0實驗室,表示感謝。
          在前兩篇文章中,使用一個單獨線程處理資源,分發到大部分的異步請求中。

          posted on 2011-01-14 10:26 nieyong 閱讀(2359) 評論(0)  編輯  收藏 所屬分類: Servlet3

          公告

          所有文章皆為原創,若轉載請標明出處,謝謝~

          新浪微博,歡迎關注:

          導航

          <2011年1月>
          2627282930311
          2345678
          9101112131415
          16171819202122
          23242526272829
          303112345

          統計

          常用鏈接

          留言簿(58)

          隨筆分類(130)

          隨筆檔案(151)

          個人收藏

          最新隨筆

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 高邑县| 霍林郭勒市| 宣化县| 许昌市| 澎湖县| 玉屏| 越西县| 舒城县| 西畴县| 珲春市| 汽车| 阜宁县| 元谋县| 论坛| 平远县| 错那县| 大姚县| 双流县| 南澳县| 周口市| 秭归县| 扶沟县| 温州市| 东乌珠穆沁旗| 南投县| 都匀市| 长沙县| 关岭| 福州市| 中卫市| 丹江口市| 景东| 金坛市| 洪江市| 鲁甸县| 基隆市| 宁海县| 平武县| 阳西县| 平江县| 栖霞市|