Google SPDY

SPDY 是 Google 開發的基於傳輸控制協議 (TCP) 的應用層協議 ,開發組正在推動 SPDY 成爲正式標準(現爲互聯網草案)。SPDY 協議旨在通過壓縮、多路複用和優先級來縮短網頁的加載時間和提高安全性。(SPDY 是 Speedy 的暱音,意思是更快)

  SPDY 與 HTTP 的關係

  SPDY 協議只是在性能上對 HTTP 做了很大的優化,其核心思想是儘量減少連接個數,而對於 HTTP 的語義並沒有做太大的修改。具體來說是,SPDY 使用了 HTTP 的方法和頁眉,但是刪除了一些頭並重寫了 HTTP 中管理連接和數據轉移格式的部分,所以基本上是兼容 HTTP 的。

  Google 在 SPDY 白皮書裏表示要向協議棧下面***並替換掉傳輸層協議(TCP),但是因爲這樣無論是部署起來還是實現起來暫時相當困難,因此 Google 準備先對應用層協議 HTTP 進行改進,先在 SSL 之上增加一個會話層來實現 SPDY 協議,而 HTTP 的 GET 和 POST 消息格式保持不變,即現有的所有服務端應用均不用做任何修改。

  因此在目前,SPDY 的目的是爲了加強 HTTP,是對 HTTP 一個更好的實現和支持。至於未來 SPDY 得到廣泛應用後會不會演一出狸貓換太子,替換掉 HTTP 並徹底顛覆整個 Internet 就是 Google 的事情了。

  爲什麼要重新建立一個 SPDY ?

  距離萬維網之父蒂姆·伯納斯-李發明並推動 HTTP 成爲如今互聯網最流行的協議已經過去十幾年了(現用 HTTP 1.1 規範也停滯了 13 年了),隨着現在 WEB 技術的飛速發展尤其是 HTML5 的不斷演進,包括 WebSockets 協議的出現以及當前網絡環境的改變、傳輸內容的變化,當初的 HTTP 規範已經逐漸無法滿足人們的需要了,HTTP 需要進一步發展,因此 HTTPbis 工作組已經被組建並被授權考慮 HTTP 2.0 ,希望能解決掉目前 HTTP 所帶來的諸多限制。而 SPDY 正是 Google 在 HTTP 即將從 1.1 跨越到 2.0 之際推出的試圖成爲下一代互聯網通信的協議,長期以來一直被認爲是 HTTP 2.0 唯一可行選擇。

  HTTP 協議的不足

1. 單路連接 請求低效

  HTTP 協議的最大弊端就是每個 TCP 連接只能對應一個 HTTP 請求,即每個 HTTP 連接只請求一個資源,瀏覽器只能通過建立多個連接來解決。此外在 HTTP 中對請求是嚴格的先入先出(FIFO)進行的,如果中間某個請求處理時間較長會阻塞後面的請求。

  (注:雖然 HTTP pipelining 對連接請求做了改善,但複雜度增加很大,並未普及)

2. HTTP 只允許由客戶端主動發起請求

  服務端只能等待客戶端發送一個請求,在可以滿足預加載的現狀是一種桎梏。

3. HTTP 頭冗餘

  HTTP 頭在同一個會話裏是反覆發送的,中間的冗餘信息,比如 User-Agent、Host 等不需要重複發送的信息也在反覆發送,浪費帶寬和資源。

  SPDY 協議的優點

1. 多路複用 請求優化

  SPDY 規定在一個 SPDY 連接內可以有無限個並行請求,即允許多個併發 HTTP 請求共用一個 TCP會話。這樣 SPDY 通過複用在單個 TCP 連接上的多次請求,而非爲每個請求單獨開放連接,這樣只需建立一個 TCP 連接就可以傳送網頁上所有資源,不僅可以減少消息交互往返的時間還可以避免創建新連接造成的延遲,使得 TCP 的效率更高。

  此外,SPDY 的多路複用可以設置優先級,而不像傳統 HTTP 那樣嚴格按照先入先出一個一個處理請求,它會選擇性的先傳輸 CSS 這樣更重要的資源,然後再傳輸網站圖標之類不太重要的資源,可以避免讓非關鍵資源佔用網絡通道的問題,提升 TCP 的性能。

2. 支持服務器推送技術

  服務器可以主動向客戶端發起通信向客戶端推送數據,這種預加載可以使用戶一直保持一個快速的網絡。

3. SPDY 壓縮了 HTTP 頭

  捨棄掉了不必要的頭信息,經過壓縮之後可以節省多餘數據傳輸所帶來的等待時間和帶寬。

4. 強制使用 SSL 傳輸協議

  Google 認爲 Web 未來的發展方向必定是安全的網絡連接,全部請求 SSL 加密後,信息傳輸更加安全。

  SPDY 協議的意義

  按照 Google 的說法,SPDY 被創造出來的唯一目的就是讓 Web 更快(strive to make the whole web fast),其名字 SPDY(Speedy) 也似乎在暗示着這一點。那麼 SPDY 的意義又在哪裏呢?

  1. 普通用戶:

  對於使用者來說,隱藏在瀏覽器下面的 SPDY 相比 HTTP 沒有任何區別,但是我們可以感覺到 Google 服務在 Chrome 下異常的快,這就是 SPDY 的功勞了。此外網站信息傳輸加密後不用擔心信息被截取等,大大增加了安全性和保密性。

  2. 前端人員:

  對於前端工程師們來說,提升頁面效率是一件很重要的事情,目前大多采用像 CSS Sprites 等方法來優化網站,對於因爲頁面加載時每張圖片、icon 都請求一個連接甚至採用在不同頁面引用不同圖片來降低一個頁面內圖片的請求數量。而現在有了 SPDY 的請求優化可以將請求順序進行重排,這樣可以在很大程度上緩解頁面加載時圖片請求帶來的影響。例如像極客公園的報名頁面,如果報名用戶過多,例如極客公園2012年創新大會或極客公園第 27 期長城會,可以很明顯的感覺出頭像的請求會拖累整體頁面加載變慢甚至變卡,相信對於這點,經常上淘寶或刷微博的會深有體會,一旦網速稍微慢點就會出現頁面加載異常,還有像蘋果 App Store(除去服務器因爲地區的延遲),豌豆莢這類應用分發平臺上應用圖標刷新緩慢等,如下面這個視頻所示。

  3. 運維人員:

  SPDY 在降低連接數目的同時,還使得服務器上每個客戶端佔用的資源也減少,從而可以釋放出更多內存和 CPU 。此外 SPDY 綜合起來可以將瀏覽速度提升一倍,頁面加載延遲方面的改進達 64% 。

  衆家支持的 SPDY 協議

  如果你在使用 Chrome 瀏覽器,同時使用像 Gmail 等 Google 的網絡服務的話,其實你已經不再是通過 HTTP 訪問這些服務了。在瀏覽器打開 chrome://net-internals/#spdy 就會發現你已經在使用 SPDY 協議了。(除了包括 Google 自家的 Gmail、Google Plus 等 Google 系服務外,其他公共站點例如 Twitter 和 Webtide 也已經支持該協議。在國內,基於 WebKit 的豌豆莢 2.0 也曾表示將引進Chrome的SPDY技術來進一步提升速度。

  SPDY 的實現需要瀏覽器客戶端和 Web 服務器同時支持。在客戶端瀏覽器這快 Google自家的 Chrome 和Chromium 全系列不用說,都已經支持SPDY; Mozilla 家的 Firefox 自 Firefox 13 也默認開啓對 SPDY 的支持。而亞馬遜家的 Silk 利用 SPDY 的深度其實不比 Google 自家的 Chrome 和 Firefox 差。

  在Web 服務器方面包括最流行和最廣泛的 Apache 在內,Netty、Jeety、Varnish、Erlang 和 Hightide 應用服務器以及面向 node.js 的服務器也都已經宣佈支持 SPDY。( Nginx 也表示將支持 SPDY)

  如何部署 SPDY?

  近日 Google 正式發佈了適用於最流行 Web 服務器 Apache 的插件 mod_spdy,將其下載安裝後你的 Apache 服務器就能使用 SPDY 協議與兼容 SPDY 協議的瀏覽器如 Chrome、FireFox 等進行通信。像之前所說的那樣,SPDY 是運行在 HTTPS 上,非 HTTPS 流量並不會受到 mod_spdy 影響。

  SPDY 部署要求:

  1. Apache 2.2 (≥2.2.4)

  2. mod_ssl 模塊開啓

  SPDY 部署步驟:

  1. 下載 mod_spdy 模塊

  到下載頁面下載對應系統的安裝包

  2. 安裝 mod_spdy 模塊

  在系統終端運行下面命令行

  dpkg -i mod-spdy-*.deb
apt-get -f install

  -系統爲 Debian/Ubuntu

  ------------------------------------------------------------

  yum install at (if you do not already have 'at' installed)
rpm -U mod-spdy-*.rpm

  -系統爲 CentOS/Fedora

  3. 重啓服務器(Apache)

  sudo /etc/init.d/apache2 restart (Debian/Ubuntu)

  4. 確定開啓與否

  打開 Chrome 瀏覽器,輸入並前往 chrome://net-internals/#spdy 頁面,查看主機名稱是否出現在標識欄中。如果出現說明已經部署完畢,如果沒有出現去服務器錯誤日誌(error.log)裏查詢。

  未來的web基礎?

  在最新的協議文檔裏 Google 重新將 SPDY 分爲了兩層,其中一層被描述爲 HTTP-like,大有取代 HTTP 的意圖(Google 最近的一篇文章已經直呼 SPDY 爲“a replacement for HTTP”)。同時 HTTP 2.0 標準制定工作組(HTTPbis)也表示,SPDY 很有希望接替當前的 HTTP 傳輸實現。

  考慮到 Chrome 和安卓的份額以及標準的推動,相信 SPDY 會有一個好前景。因此選擇此刻支持 SPDY 也是明智的選擇。







本文主要是參考Google SPDY項目主頁的一些文檔總結而來,目的整體上介紹SPDY協議的定義爲主。後續,我將寫一系列的文章分析SPDY的一些項目(如:Nginx),SPDY的性能測試以及如何部署SPDY到實際生產應用。

一、HTTP協議存在的一些主要問題

1、一個連接一個請求。瀏覽器和web server之間都是以短連接方式交互,一個連接只服務一次請求,對於一個需要加載多個資源的頁面來說,將會帶來很高的延遲。
2、只能由客戶端發起請求,服務器完成響應。服務器不能主動的將一些必須的資源推送給客戶端。
3、HTTP協議只能對body進行壓縮處理,不能壓縮header。在一個cookie較多的站點,將對帶寬造成嚴重的浪費。

http的問題在10年前的web中,是無關緊要的。然而今天的web已不再像10年的web那般簡單了,同時用戶對web應用的體驗要求也將是越來越高,所以Google發起了“Let's make the web faster“項目,SPDY正是此項目的一部分。

二、SPDY的目標
起初,SPDY項目並不只是爲了加速http,更多的是要致力於改進傳輸層和會話層協議。比如: Stream Control Transmission Protocol (SCTP), 一個用於替換TCP的傳輸層協議。除此之外還有一些其他方面的研究,可以在相應的white paper上找到。開發一個新的傳輸層協議也許很簡單,但考慮到後期的部署、推廣和兼容歷史等因素,這估計是一個非常糟糕的決定,等待的結果必然是失敗。因此,目前的SPDY主要還是集中應用層協議的改進,加速HTTP。

SPDY的主要目標:
1、單個tcp連接支持併發的Http請求。這主要是解決目前http協議的一個連接只能服務一次請求的問題。
2、壓縮請求/響應頭。
3、定義spdy爲一個相比http容易實現的協議。
4、使用ssl加密連接,用戶數據更加安全的同時也解決了對已有網絡體系的兼容問題。其實,TLS的強制,更多的是解決歷史兼容問題,而不是安全考慮,後面詳細介紹。
5、服務器可以主動的向客戶端發起連接,並推送數據。

三、SPDY協議棧
在http協議棧中引入spdy後,大概就是下圖(來自Google官方)的樣子:

1341806631_6446.png

關鍵就是在tcp連接上面加入了spdy session層,這一層根據spdy draft又可以稱爲framing層,主要提供stream機制和消息組幀的實現。下文介紹具體協議的時候,再談。

四、TLS-NPN
TLS-NPN全稱是Transport Layer Security - Next Protocol Negotiation,NPN是Google爲了支持SPDY協議作爲一個應用層協議使用,而爲TLS定義的一個擴展。NPN擴展的出現僅僅是爲了更好的部署和使用SPDY,任何時候它都不會是SPDY的一部分。關於NPN擴展的詳細介紹請看這裏:http://technotes.googlecode.com/git/nextprotoneg.html

既然TLS-NPN並不是SPDY協議的一部分,那爲什麼要強制TLS?爲何不能像HTTP一樣根據用戶自由選擇是否SSL呢?Google這樣做,必然是有道理的:
1、目前整個互聯網可以說只有80和443兩個端口可用,如果SPDY跑在一個新的端口上提供web服務,就極有可能會被諸如防火牆等設施給阻止掉。要想推動整個網絡系統引入一個新的等同於80和443的標準端口,我想這絕對不是一件容易的事情,因此聰明的Google必須考慮兼容現在的網絡體系環境,而不是自作聰明的推動新的端口。
2、放棄使用新端口的方案,就只能在80和443上面選擇了。然而,目前很多的web中間代理設施只認80端口跑http協議,一旦SPDY跑在80端口上,必然會被這些代理給阻止掉。80端口顯然也不能使用。
3、沒了80端口,就只能選擇443了,443目前是https協議加密數據傳輸,理論上443端口上經過加密的套接字可以傳輸任何應用層協議數據。
因此,爲了在SSL上能夠協商使用SPDY協議,Google就定義了NPN擴展,此擴展目前已經在OpenSSL、NSS等實現了。

五、SPDY-draft2
Google已經放出的SPDY協議草案在此: http://www.chromium.org/spdy/spdy-protocol ,目前已經到draft4了,但本文參考的是draft2,因爲目前Nginx的SPDY實現是基於draft2而來。

SPDY在邏輯上由部分構成,一是framing layer,其主要負責組裝幀消息,爲了request/response提供基礎;二是HTTP layer,它定義了request/response的相關行爲。
1341806886_1928.png
根據上面這個簡單的模型,從總體上看一下SPDY的3個重要組成部分——TCP connection、framing layer、http layer。
上圖描述的是client和server之間的一個TCP連接;這個TCP連接上面有兩個stream,一個stream就負責了一次request/response;一個request/response由多個frame(一個小箭頭就是一個frame)組成;frame又分爲了control frame (紅色箭頭)和data frame (藍色箭頭)。framing layer主要是定義一個frame消息,HTTP layer主要是定義request/response。

一次request/response完成後,就釋放此stream,但不會釋放TCP connection。要發起新的request,首先得建立一個stream,由此可看出SPDY在TCP connection上加入了stream機制來模擬了http的短連接。stream其實只是TCP上面的一個邏輯層,它的建立和釋放非常快,沒有TCP的多次握手,這就解決了TCP的Slow Start問題。換個角度想想,如果TCP connection的建立和釋放本來就無延遲,非常的快速,那麼http就沒有改進的必要了,我猜想這也是一開始Google想從傳輸協議TCP入手解決問題的考慮。

Framing
Framing分爲control和data兩種,下面詳細介紹SPDY定義了哪些control frame和data frame,他們的作用是什麼。

control frame結構

 +----------------------------------+
 |C| Version(15bits) | Type(16bits) |
 +----------------------------------+
 | Flags (8)  |  Length (24 bits)   |
 +----------------------------------+
 |               Data               |
 +----------------------------------+

上圖可以看到一個control frame至少有8個字節的頭部信息。
C:           佔一個bit,用來識別此frame是control還是data之用。
Version:  佔15個bit,是SPDY的版本號,目前是2。
Type:      佔16個bit,control frame的類型,表示此control frame具體是幹什麼用,後面將介紹每種類型的control frame。
Flags:      佔8個bit,一個附加的屬性域。
Length:   佔24個bit,其實是一個無符號的24位整數,表示Length域後面的數據長度。


data frame結構
 +----------------------------------+
 |C|       Stream-ID (31bits)       |
 +----------------------------------+
| Flags (8)  |  Length (24 bits)   |
 +----------------------------------+
 |               Data               |
 +----------------------------------+

同樣可以看出一個data frame至少也有8個字節的頭部信息。
C:                    同control frame。
Stream-ID:       佔31bit,一個stream的標誌id。
Flags和Length: 同control frame。

stream
SPDY的一個stream既可以被client創建,也可以被server創建,這就說明SPDY不但允許由client發起請求,也可以由server發起請求。如果你願意,還可以創建一個單向stream,只需要發送特定的control frame就可以了,單向stream可以認爲是隻有請求,永遠不會有響應。stream的創建、關閉等操作都是由control frame實現的。

control frames
SPDY定義了不少的control frames,這裏簡單的列舉一下它們,不作詳細的介紹,如果你在實現SPDY的時候,請求看具體draft。

SYN_STREAM control frame - 是發送者用來創建一個stream。
SYN_REPLY control frame - SYN_STREAM接受者用此control frame去開始響應對方。
RST_STREAM control frame - 可以用來中斷一個stream。
SETTINGS control frame - 可以用來改變一個stream的狀態,屬性等。
NOOP control frame - 是一個無操作的control frame了,接受者直接忽略它。
PING control frame - 類似ping命令的功能,可以用來測量一個rtt時間。ping工具是工作在4層,此處的PING control frame卻是工作在7層上。
GOAWAY control frame - 發送者用來告訴對端,不再接受新的stream了。可以理解爲不久將要關鍵當前的TCP connection。
HEADERS control frame - 給stream添加一些附加的header。

到此,各種control frame都簡單的介紹完了,每個frame的具體定義還得參考draft。至於datat frame,相比control frame就簡單多了,它沒有這麼類型,它只做一件事情——就是在某個stream上傳輸數據。

HTTP layer
爲了兼容目前的所有應用,儘量做到應用不做任何修改,或者儘可能少的修改。因此http layer定義瞭如何將http request/response跑在framing之上。

客戶端通過SYN_STREAM control frame發起一個請求,請求相關的所有header放在SYN_STREAM frame中發送,如果請求有body將在data frame中發送,最後一個data frame必須設置FIN_FLAG標誌請求結束。
服務器通過SYN_REPLY control frame響應客戶端,響應的所有header放在SYN_REPLY frame中發送,響應數據通過data frame來發送,同樣最後一個data frame需要設置FIN_FLAG標誌響應結束。

SPDY還詳細的定義http request/response headers的異同,具體看草案。

server push
有了push功能就可以針對一個客戶端請求響應多個應答,這樣可以避免針對每個資源的獲取,客戶端都要主動來請求一次;相反,服務器主動將這樣一些明知客戶端需要的資源推送給客戶端。push功能的實現感覺還是挺複雜的,具體參考spdy-draft。

SPDY 部署
1、服務器通過Alternate-Protocol header來建議使用SPDY
服務器收到一個普通的http請求的時候,可以通過在響應header裏添加Alternate-Protocl來告知客戶端可以發送SPDY。客戶端收到Alternate-Protocl header後,就嘗試去通過SPDY發送請求給服務器,如果失敗了,在當前域下,就再也不要去嘗試做這件事情了。

2、服務器通過TLS-NPN擴展來建議使用SPDY
服務器在443端口收到一個攜帶有TLS-NPN擴展的連接,就告訴客戶端自己所支持的spdy版本號,然後客戶端就通過SPDY來和服務器通信。通過TLS-NPN擴展的方式應該是唯一的途徑在整個互聯網上使用。Alternate-Protocol的方式只有在確定客戶端和服務器中間沒有拒絕其他端口的防火牆等設施才ok。

SPDY的現狀
目前Google,twitter,facebook等公司都已經開始着手部署spdy來加速自己的web應用了。在服務器方面,Apache、Nginx、Netty、Jetty、node.js等都已經開始初步的支持SPDY。瀏覽器方面,chrome已經支持SPDY,firefox貌似也開始支持了。其次,在github上搜索一下SPDY,可以看到有不少spdy的項目存在了。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章