1.HTTP的瓶頸
在 Facebook 和 Twitter 等 SNS 網(wǎng)站上,幾乎能夠?qū)崟r(shí)觀察到海量用戶公開發(fā)布的內(nèi)容坎弯,這也是一種樂趣纺涤。當(dāng)幾百、幾千萬的用戶發(fā)布內(nèi)容時(shí)抠忘,Web 網(wǎng)站為了保存這些新增內(nèi)容撩炊,在很短的時(shí)間內(nèi)就會(huì)發(fā)生大量的內(nèi)容更新.為了盡可能實(shí)時(shí)地顯示更新的內(nèi)容,服務(wù)器上一有內(nèi)容更新崎脉,就需要直接把那些內(nèi)容反饋到客戶端的界面上拧咳。雖然看起來挺簡單的,但 HTTP 卻無法妥善地處理好這項(xiàng)任務(wù)囚灼。
使用 HTTP 協(xié)議探知服務(wù)器上是否有內(nèi)容更新骆膝,就必須頻繁地從客戶端到服務(wù)器端進(jìn)行確認(rèn)。如果服務(wù)器上沒有內(nèi)容更新灶体,那么就會(huì)產(chǎn)生徒勞的通信阅签。
若想在現(xiàn)有 Web 實(shí)現(xiàn)所需的功能,以下這些 HTTP 標(biāo)準(zhǔn)就會(huì)成為瓶頸蝎抽。
a.一條連接上只可發(fā)送一個(gè)請求政钟。
b.請求只能從客戶端開始≌两幔客戶端不可以接收除響應(yīng)以外的指令锥涕。
c.請求 / 響應(yīng)首部未經(jīng)壓縮就發(fā)送。首部信息越多延遲越大狭吼。
d.發(fā)送冗長的首部层坠。每次互相發(fā)送相同的首部造成的浪費(fèi)較多。
e.可任意選擇數(shù)據(jù)壓縮格式刁笙。非強(qiáng)制壓縮發(fā)送破花。
Ajax的解決方法: Ajax(Asynchronous JavaScript and XML谦趣, 異 步 JavaScript 與 XML 技術(shù))是一種有效利用 JavaScript 和 DOM(Document Object Model,文檔對(duì)象模型)的操作座每,以達(dá)到局部 Web 頁面替換加載的異步通信手段前鹅。和以前的同步通信相比,由于它只更新一部分頁面峭梳,響應(yīng)中傳輸?shù)臄?shù)據(jù)量會(huì)因此而減少舰绘,這一優(yōu)點(diǎn)顯而易見。
Ajax 的核心技術(shù)是名為 XMLHttpRequest 的 API葱椭,通過 JavaScript 腳本語言的調(diào)用就能和服務(wù)器進(jìn)行 HTTP 通信捂寿。借由這種手段,就能從已加載完畢的 Web 頁面上發(fā)起請求孵运,只更新局部頁面秦陋。
而利用 Ajax 實(shí)時(shí)地從服務(wù)器獲取內(nèi)容,有可能會(huì)導(dǎo)致大量請求產(chǎn)生治笨。另外驳概,Ajax 仍未解決 HTTP 協(xié)議本身存在的問題。
Comet 的解決方法: 一旦服務(wù)器端有內(nèi)容更新了旷赖,Comet 不會(huì)讓請求等待顺又,而是直接給客戶端返回響應(yīng)。這是一種通過延遲應(yīng)答等孵,模擬實(shí)現(xiàn)服務(wù)器端向客戶端推送(Server Push)的功能待榔。
通常,服務(wù)器端接收到請求流济,在處理完畢后就會(huì)立即返回響應(yīng),但為了實(shí)現(xiàn)推送功能腌闯,Comet 會(huì)先將響應(yīng)置于掛起狀態(tài)绳瘟,當(dāng)服務(wù)器端有內(nèi)容更新時(shí),再返回該響應(yīng)姿骏。因此糖声,服務(wù)器端一旦有更新,就可以立即反饋給客戶端分瘦。
內(nèi)容上雖然可以做到實(shí)時(shí)更新蘸泻,但為了保留響應(yīng),一次連接的持續(xù)時(shí)間也變長了嘲玫。期間悦施,為了維持連接會(huì)消耗更多的資源。另外去团,Comet 也仍未解決 HTTP 協(xié)議本身存在的問題抡诞。
2.SPDY
SPDY 沒有完全改寫 HTTP 協(xié)議穷蛹,而是在 TCP/IP 的應(yīng)用層與運(yùn)輸層之間通過新加會(huì)話層的形式運(yùn)作。同時(shí)昼汗,考慮到安全性問題肴熏,SPDY 規(guī)定通信中使用 SSL。
SPDY 以會(huì)話層的形式加入顷窒,控制對(duì)數(shù)據(jù)的流動(dòng)蛙吏,但還是采用 HTTP 建立通信連接。因此鞋吉,可照常使用 HTTP 的 GET 和 POST 等方 法鸦做、Cookie 以及 HTTP 報(bào)文等.
多路復(fù)用流: 通過單一的 TCP 連接,可以無限制處理多個(gè) HTTP 請求坯辩。所有請求的處理都在一條 TCP 連接上完成馁龟,因此 TCP 的處理效率得到提高。
賦予請求優(yōu)先級(jí): SPDY 不僅可以無限制地并發(fā)處理請求漆魔,還可以給請求逐個(gè)分配優(yōu)先級(jí)順序坷檩。這樣主要是為了在發(fā)送多個(gè)請求時(shí),解決因帶寬低而導(dǎo)致響應(yīng)變慢的問題改抡。
壓縮 HTTP 首部: 壓縮 HTTP 請求和響應(yīng)的首部矢炼。這樣一來,通信產(chǎn)生的數(shù)據(jù)包數(shù)量和發(fā)送的字節(jié)數(shù)就更少了阿纤。
推送功能: 支持服務(wù)器主動(dòng)向客戶端推送數(shù)據(jù)的功能句灌。這樣,服務(wù)器可直接發(fā)送數(shù)據(jù)欠拾,而不必等待客戶端的請求胰锌。
服務(wù)器提示功能: 服務(wù)器可以主動(dòng)提示客戶端請求所需的資源。由于在客戶端發(fā)現(xiàn)資源之前就可以獲知資源的存在藐窄,因此在資源已緩存等情況下资昧,可以避免發(fā)送不必要的請求。
3.WebSocket
WebSocket 協(xié)議的主要特點(diǎn)
推送功能: 支持由服務(wù)器向客戶端推送數(shù)據(jù)的推送功能荆忍。這樣格带,服務(wù)器可直接發(fā)送數(shù)據(jù),而不必等待客戶端的請求刹枉。
減少通信量: 只要建立起 WebSocket 連接叽唱,就希望一直保持連接狀態(tài)。和 HTTP 相比微宝,不但每次連接時(shí)的總開銷減少棺亭,而且由于 WebSocket 的首部信息很小,通信量也相應(yīng)減少了蟋软。
只要建立起 WebSocket 連接侦铜,就希望一直保持連接狀態(tài)专甩。和 HTTP 相比,不但每次連接時(shí)的總開銷減少钉稍,而且由于 WebSocket 的首部信息很小涤躲,通信量也相應(yīng)減少了。
為了實(shí)現(xiàn) WebSocket 通信贡未,在 HTTP 連接建立之后种樱,需要完成一次“握手”(Handshaking)的步驟。
a.請求
為了實(shí)現(xiàn) WebSocket 通信俊卤,需要用到 HTTP 的 Upgrade 首部字段嫩挤,告知服務(wù)器通信協(xié)議發(fā)生改變,以達(dá)到握手的目的消恍。
Sec-WebSocket-Key 字段內(nèi)記錄著握手過程中必不可少的鍵值岂昭。Sec-WebSocket-Protocol 字段內(nèi)記錄使用的子協(xié)議。子協(xié)議按 WebSocket 協(xié)議標(biāo)準(zhǔn)在連接分開使用時(shí)狠怨,定義那些連接的名稱约啊。
b.響應(yīng)
對(duì)于之前的請求,返回狀態(tài)碼 101 Switching Protocols 的響應(yīng)佣赖。
Sec-WebSocket-Accept 的字段值是由握手請求中的 Sec-WebSocket-Key 的字段值生成的恰矩。
成功握手確立 WebSocket 連接之后,通信時(shí)不再使用 HTTP 的數(shù)據(jù)幀憎蛤,而采用 WebSocket 獨(dú)立的數(shù)據(jù)幀外傅。
c.webSocket API
JavaScript 可調(diào)用“The WebSocket API”(http://www.w3.org/TR/websockets/,由 W3C 標(biāo)準(zhǔn)制定)內(nèi)提供的 WebSocket 程序接口俩檬,以實(shí)現(xiàn) WebSocket 協(xié)議下全雙工通信萎胰。以下為調(diào)用 WebSocket API,每 50ms 發(fā)送一次數(shù)據(jù)的實(shí)例棚辽。