最近想自己實作的 Comet 架構

甚麼是 Comet ?

自從 Facebook , Plurk 流行起來 , Comet 技術才被受到重視 , 之前曾經搜尋了 Google 上各種有關 Comet 的資訊 , 其實早在 5 年前(西元2005)我就實作過了 , 當時是在一家叫互動王視訊科技的公司做了個股票看盤系統 , 就是類似 Comet 的技術 , 我在該公司任職前 , 已經有了一個股票看盤系統 , 也是類似 Comet , 我去了是把原本前人寫的 Perl 版寫的完全改成 PHP 版的 , 因此 Google 上搜尋到有關 Comet 的 WIKI 說 2006 出現了第一個 Comet 應用 (http://en.wikipedia.org/wiki/Comet_%28programming%29#First_Comet_applications) , 原來 , 這東西我及互動王的前人早就做過了 , 哈 !

但可能有人對 Comet 還不太了解是甚麼 , 其實 Comet 並不是一種制式的協定 , 這是一種概念 , 就如同 AJAX 也是種概念 , Comet 主要用意是要讓 Browser 得到即時的資訊並且做到雙向互動 , 但我們都知道 , Web Browser 是要 Client 端主動要求某個網址 , Web Server 才會送資料來 , 即便是 AJAX 概念也是如此 , 那麼如何讓 Client 端不斷接收即時資料呢 ?

Server Push

早在 1995 年 , Netscape 瀏覽器支援了 Server Push 的 HTTP 封包協定 , 此封包協定可以讓 Server 端在不斷線的情形下一直發送資料給 Client 端的 Browser , 但Server Push 技術一直沒有流行的原因 , 我想是因為它並沒有成為 W3C 標準 , 且 IE 並不支援 , 因此這種協定雖然早就有了 , 但在當時 IE 稱霸天下的情形下並沒有太多人使用

另外 Server Push 在早期有一個很要命的技術缺陷 , 因為 Apache Httpd 從很早以前到現在就一直是 Web Server 佔有率最高的軟體 , 在 Apache 1.x 的時代 , 每一條 http 連線都會產生一個子行程 , 那如果同時有 100 人連線 , 就會產生 100 個子行程 , 對於 Server 的負擔極大 , 因此要提供 Server Push 的服務也僅能同時提供給數百人使用 , 即便是現在 Apache 2.x 雖然有支援多執行緒或 event 的 MPM 模組 , 但是大多數仍是用 prefork 模組 , 這樣就和 Apache 1.x 的方式一樣 , 仍無法提供大量連線服務

好吧 , 就算有人想用Apache MPM 模組 , 或者可能有人玩過 lighttpd 這類的只要用一個行程就可以收大量連線 , 那這樣應該沒問題吧 ? 但這仍要考量到撰寫 Web 應用大部分的人會採用的程式語言 , 我想 PHP 應該是目前很多人用的吧 , 如果是用 Apache MPM 或 lighttpd , 最好的架構就是採用 PHP FastCGI 與 Web Server 搭配 , 但是當採用這種架構的時候 , 變成瓶頸會在 PHP 上頭 , 雖然 Web Server 可以接收大量連線且有效降低子行程 , 但是 PHP FastCGI 仍然是一個行程服務一次 Client 端的 request , 也就是說若同時有 100 條連線 , 那麼 OS 就會看到有 100 個 php 行程在跑 , 所以這種架構也不適合 , 當然這是 PHP FastCGI 本身架構的問題啦

也許可以用其他語言如 C  , Perl , Java 語言來撰寫 Fast CGI 就可在一個行程中服務多個連線 , 但這類作法會衍生其它的問題 ,  尤其必須注意到記憶體共用及配置的問題 , 因此在開發的速度及 Debug 上問題較多 , 當然也有人說那為何不直接用 java 的 servlet 就好了 !! 恩 ~~~ 其實 servlet 的處理速度挺快的 , 且可以避免記憶體共用的問題 , 但 servlet 仍是有個問題 , 就是大量連線時候 , 產生的執行緒過多仍然會造成效能問題

Long Polling

這個名詞也是在 Google 上查閱資料看到的 , 其實是透過 IFRAME 不斷的接收 Server 傳來的資料 , 傳來的資料會是 javascript 指令, 例如以下程式碼

<script>top.echotime( "11:00:11");</script>

<script>top.echotime("11:00:12");</script>

...... 每一秒可能收到類似的指令

在 IFRAME 不斷線的情形下 , 其實瀏覽器會繼續執行 <script> 內的東西 , 當然這技術比 Server Push 好 , 因為不用考慮到相容性問題 , 但和 Server Push 一樣會佔用 httpd server 的行程 , 我在互動王實作的股票看盤也是用這種技術實作的 , 這有個小問題 , 就是一直收資料也會造成 Browser 記憶體一直耗用 , 所以在送出一段時間後 , 可能要讓 Server 與 Client 斷線 , 然後重新連接

自行實作 Http Application Server

上面提到過 Server Push 的效能問題 , 那麼有沒有可能解決呢 ???

有的 , 就是自己作一個 Http Server , 這個 Http Server 可能是專門執行某項任務的小型 Server  ,  不會產生太多的執行緒 , 沒有任何權限控管(例如 apache 的 .htaccess 功能) , 也可能不能執行 CGI 或 FastCGI , 因為所有的任務程式都已經寫在 HTTP Server 內了 , 因此在記憶體用量上及處理速度都可以滿足大量連線的需求 , 但是要自己實作 HTTP Application Server 要對 Socket Programing 及 HTTP 協定都要很清楚 , 也不是一般人能幹的 , 不過目前仍然是有現成的 Open Source 方案可以用 , Google 上搜尋 Comet 字串應該會看到許多 , 例如 node.js 就是以 Google V8 去實作的 , 可以用 javascript 實現 Server 端的 Http Server , 也有 C# 寫成的 WebSync(非 opensource) , 還有很多類似的技術我想都會慢慢有人做好後提供出來

雖然已經有現成的物件可用 ,  但是我仍然想要自己搞一個 , 因此我正在開發 NetServ , 我主要的想法是用 C# 撰寫自己的 HTTP Server 類別 , 這個類別可能只會處理 HTTP 封包 , 甚麼功能都沒有 , 讓程式設計師可以開發出資源耗用最少的 Server , 我會選用 C# 的原因是 , 跨平台 , .NET 類別庫的功能多且支援非同步Socket , C# 很流行 , 至於為何我不用 C 開發 ? 我沒那麼厲害是主要原因  , 而且用 C 來實作 Comet ... 可能也不是大部份的人想幹的 ,  , 當然 java 也可以實做得出來 , 但是 java 虛擬機佔用的記憶體我仍然嫌太大 , 且好像沒看過有非同步 Socket .. 況且經過我實際的效能測試 , C# 寫出的非同步 Socket 的執行速度挺不賴的 , 所以我才有此想法

目前只實作出一個簡單的 Socket Server 類別放到 NetServ 專區 , 目前尚未實作出 Http Server , 但已經有一個效能測試範例 , 但我提出這想法也是拋磚引玉啦 , 看有沒有人看過類似的  , 若有 , 我也不想那麼麻煩 , 反正也是當作練習 , 哈

5 則評論在 最近想自己實作的 Comet 架構.

  1. 真厲害耶!看著看著我也好想也來研究甚麼看看…
    沒記錯的話中衛發展中心有針對中小企業的”創新服務”補助方案喔,
    比如發展出新的服務應用(概念階段的也可以的樣子),說不定這個技術左右未來網路應用服務的發展!?
    (其實這篇文章我看了四遍才看懂XD)

  2. 通告: 我一個半途夭折的想法 « 色胚子部落

  3. 哈囉!前同事您好啊!

    我也是”前朝”遺老,在總經理室編制內,就是一堆女生的那區啦!
    每天負責畫大餅的。
    之前應該見過面吧?那時與寫game的程式工程師較熟。
    目前也還存活於網路行銷界,有空回mail給我吧!

    David

發佈留言