2010-01-04 32 views
11

要使用web sockets實現支持客戶端的服務器,服務器是否與每個客戶端保持開放的HTTP連接?這如何擴展?Web套接字服務器端處理模型

什麼是實施此類服務器時的「編程模型」?也就是說:大多數Web應用程序都有支持connect-> request-> response-> close類型的servlet等。而使用網絡套接字時,連接保持無限期打開狀態。

回答

17

您通常需要在asynchronous模型中工作這些長期連接才能工作。有幾種不同的技術來完成異步I/O;所有這些都有其優點和缺點。

一個應該已經熟悉任何使用JavaScript和AJAX的人都是回調模型;在其中發送一個請求,並安裝一個回調,當它完成時被調用。這是XMLHTTPRequest的工作方式,在等待一頁請求完成時不阻止所有其他頁面。這也是Python網絡框架的工作原理,儘管它可以根據您使用的接口調用對象上的方法或回調函數。

另一個強大的模型是Erlang風格的方法,稱爲Actor模型,有許多很多輕量級進程(像線程但沒有共享狀態),每個進程都通過異步消息相互通信。 Erlang運行時已經實現,可以產生數千個非常高效的進程;那麼您可以爲每個連接創建一個進程,並讓他們將消息發送到實現應用程序後端的其他進程。 Erlang進程也可以在多個OS線程上自動調度,以充分利用多核系統。 ejabberd是一種流行的Jabber服務器(一種聊天協議,它需要許多長期的開放式連接),在Erlang中也是如此,其中Facebook Chat system也是如此。

來自Google的新的Go language採用了類似的方法,比Erlang的Actor模型更接近於Hoare的通信順序,但它有很多相似之處。

在Mac OS X 10.6中,Apple引入了Grand Central Dispatch以及C,C++和Objective-C中的塊(基本上是閉包)。這允許類似於AJAX或Twisted風格的事件驅動回調模型,但具有按順序執行的顯式管理隊列,以管理對多線程多核環境中共享資源的訪問。 Twisted和JavaScript都運行單線程,因此只能利用單個內核,除非使用多個操作系統進程,這些進程可能相當重,並增加了它們之間的通信成本。

然後有更傳統的模型,如Unix select函數,或更現代和有能力的epollkqueue()。在這些應用程序中,通常在程序中有一個主循環,它建立了一系列需要監視的事件(網絡I/O返回更多數據,文件I/O返回更多數據,創建新的網絡連接等) ,然後調用阻塞的系統調用,直到其中一個事件發生,此時您檢查發生了哪一個事件,然後進行適當的處​​理。這些系統調用通常用於提供上述更高級別的框架。

有關可用選項(關注更傳統的和更低級別的Unix方法)的非常好的概述,請參閱The C10K Problem,這是一項幫助同時處理10,000個同時連接的不同技術調查。這也有一個很好的C和C++庫列表,用於抽象各種可用的API,如libevent

當然,最後一個選項是爲每個連接使用一個進程或一個OS線程。問題是,過程的重量非常重,甚至與許多這些選項相比,線程的重量也相當重。通常,爲了獲得最佳性能,您希望每個CPU都有一個進程或線程,每個都使用異步I/O API來確定何時需要執行工作,然後將該工作分派到多個對象或回調中的一個已經被註冊來處理連接,或者正在等待消息的幾個Erlang樣式的輕量級進程之一,或者類似的東西。

請注意,web套接字中的連接不是HTTP連接,而是一個新協議,即websocket protocol,儘管您可以使用與HTTP相同的端口,並且將HTTP連接升級到web套接字以便與現有防火牆規則兼容。

0

一般來說,您應該期望使用WebSockets和用於輕量級處理負載的自定義服務器實現。這種服務器已經存在用於長期COMET連接等等。

0

它與http的不同之處在於每個後續的請求/響應不需要被包裝在具有http頭的http消息中。所以實時應用程序不需要解析標題的開銷。在最初的類似於http的握手之後,它基本上像普通的ol'tcp套接字一樣。

這可以使用servlet建模,但只需要區分初始請求(包含所有頭文件)和隨後的雙向對話框,其格式在大多數情況下是任意的。