標籤:blog mac os har 串連 不同的 資料壓縮 虛擬機器主機 提高 patch
HTTP 協議是互連網的基礎協議,也是網頁開發的必備知識,最新版本 HTTP/2 更是讓它成為技術熱點。
轉自:http://www.ruanyifeng.com/blog/2016/08/http.html
本文介紹 HTTP 協議的曆史演變和設計思路。
一、HTTP/0.9
HTTP 是基於 TCP/IP 協議的應用程式層協議。它不涉及資料包(packet)傳輸,主要規定了用戶端和伺服器之間的通訊格式,預設使用80連接埠。
最早版本是1991年發布的0.9版。該版本極其簡單,只有一個命令GET。
GET /index.html
上面命令表示,TCP 串連(connection)建立後,用戶端向伺服器請求(request)網頁index.html。
協議規定,伺服器只能回應HTML格式的字串,不能回應別的格式。
<html> <body>Hello World</body></html>
伺服器發送完畢,就關閉TCP串連。
二、HTTP/1.02.1 簡介
1996年5月,HTTP/1.0 版本發布,內容大大增加。
首先,任何格式的內容都可以發送。這使得互連網不僅可以傳輸文字,還能傳輸映像、視頻、二進位檔案。這為互連網的大發展奠定了基礎。
其次,除了GET命令,還引入了POST命令和HEAD命令,豐富了瀏覽器與伺服器的互動手段。
再次,HTTP請求和回應的格式也變了。除了資料部分,每次通訊都必須包括頭資訊(HTTP header),用來描述一些中繼資料。
其他的新增功能還包括狀態代碼(status code)、多字元集支援、多部分發送(multi-part type)、許可權(authorization)、緩衝(cache)、內容編碼(content encoding)等。
2.2 請求格式
下面是一個1.0版的HTTP請求的例子。
GET / HTTP/1.0User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5)Accept: */*
可以看到,這個格式與0.9版有很大變化。
第一行是請求命令,必須在尾部添加協議版本(HTTP/1.0)。後面就是多行頭資訊,描述用戶端的情況。
2.3 回應格式
伺服器的回應如下。
HTTP/1.0 200 OK Content-Type: text/plainContent-Length: 137582Expires: Thu, 05 Dec 1997 16:00:00 GMTLast-Modified: Wed, 5 August 1996 15:55:28 GMTServer: Apache 0.84<html> <body>Hello World</body></html>
回應的格式是"頭資訊 + 一個空行(\r\n) + 資料"。其中,第一行是"協議版本 + 狀態代碼(status code) + 狀態原因"。
2.4 Content-Type 欄位
關於字元的編碼,1.0版規定,頭資訊必須是 ASCII 碼,後面的資料可以是任何格式。因此,伺服器回應的時候,必須告訴用戶端,資料是什麼格式,這就是Content-Type欄位的作用。
下面是一些常見的Content-Type欄位的值。
- text/plain
- text/html
- text/css
- image/jpeg
- image/png
- image/svg+xml
- audio/mp4
- video/mp4
- application/javascript
- application/pdf
- application/zip
- application/atom+xml
這些資料類型總稱為MIME type,每個值包括一級類型和二級類型,之間用斜杠分隔。
除了預定義的類型,廠商也可以自訂類型。
application/vnd.debian.binary-package
上面的類型表明,發送的是Debian系統的位元據包。
MIME type還可以在尾部使用分號,添加參數。
Content-Type: text/html; charset=utf-8
上面的類型表明,發送的是網頁,而且編碼是UTF-8。
用戶端請求的時候,可以使用Accept欄位聲明自己可以接受哪些資料格式。
Accept: */*
上面代碼中,用戶端聲明自己可以接受任何格式的資料。
MIME type不僅用在HTTP協議,還可以用在其他地方,比如HTML網頁。
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><!-- 等同於 --><meta charset="utf-8" />
2.5 Content-Encoding 欄位
由於發送的資料可以是任何格式,因此可以把資料壓縮後再發送。Content-Encoding欄位說明資料的壓縮方法。
Content-Encoding: gzipContent-Encoding: compressContent-Encoding: deflate
用戶端在請求時,用Accept-Encoding欄位說明自己可以接受哪些壓縮方法。
Accept-Encoding: gzip, deflate
2.6 缺點
HTTP/1.0 版的主要缺點是,每個TCP串連只能發送一個請求。發送資料完畢,串連就關閉,如果還要請求其他資源,就必須再建立一個串連。
TCP串連的建立成本很高,因為需要用戶端和伺服器三向交握,並且開始時發送速率較慢(slow start)。所以,HTTP 1.0版本的效能比較差。隨著網頁載入的外部資源越來越多,這個問題就愈發突出了。
為瞭解決這個問題,有些瀏覽器在請求時,用了一個非標準的Connection欄位。
Connection: keep-alive
這個欄位要求伺服器不要關閉TCP串連,以便其他請求複用。伺服器同樣回應這個欄位。
Connection: keep-alive
一個可以複用的TCP串連就建立了,直到用戶端或伺服器主動關閉串連。但是,這不是標準欄位,不同實現的行為可能不一致,因此不是根本的解決辦法。
三、HTTP/1.1
1997年1月,HTTP/1.1 版本發布,只比 1.0 版本晚了半年。它進一步完善了 HTTP 協議,一直用到了20年後的今天,直到現在還是最流行的版本。
3.1 持久串連
1.1 版的最大變化,就是引入了持久串連(persistent connection),即TCP串連預設不關閉,可以被多個請求複用,不用聲明Connection: keep-alive。
用戶端和伺服器發現對方一段時間沒有活動,就可以主動關閉串連。不過,規範的做法是,用戶端在最後一個請求時,發送Connection: close,明確要求伺服器關閉TCP串連。
Connection: close
目前,對於同一個網域名稱,大多數瀏覽器允許同時建立6個持久串連。
3.2 管道機制
1.1 版還引入了管道機制(pipelining),即在同一個TCP串連裡面,用戶端可以同時發送多個請求。這樣就進一步改進了HTTP協議的效率。
舉例來說,用戶端需要請求兩個資源。以前的做法是,在同一個TCP串連裡面,先發送A請求,然後等待伺服器做出回應,收到後再發出B請求。管道機制則是允許瀏覽器同時發出A請求和B請求,但是伺服器還是按照順序,先回應A請求,完成後再回應B請求。
3.3 Content-Length 欄位
一個TCP串連現在可以傳送多個回應,勢必就要有一種機制,區分資料包是屬於哪一個回應的。這就是Content-length欄位的作用,聲明本次回應的資料長度。
Content-Length: 3495
上面代碼告訴瀏覽器,本次回應的長度是3495個位元組,後面的位元組就屬於下一個回應了。
在1.0版中,Content-Length欄位不是必需的,因為瀏覽器探索服務器關閉了TCP串連,就表明收到的資料包已經全了。
3.4 分塊傳輸編碼
使用Content-Length欄位的前提條件是,伺服器發送回應之前,必須知道回應的資料長度。
對於一些很耗時的動態操作來說,這意味著,伺服器要等到所有操作完成,才能發送資料,顯然這樣的效率不高。更好的處理方法是,產生一塊資料,就發送一塊,採用"流模式"(stream)取代"緩衝模式"(buffer)。
因此,1.1版規定可以不使用Content-Length欄位,而使用"分塊傳輸編碼"(chunked transfer encoding)。只要請求或回應的頭資訊有Transfer-Encoding欄位,就表明回應將由數量未定的資料區塊組成。
Transfer-Encoding: chunked
每個非空的資料區塊之前,會有一個16進位的數值,表示這個塊的長度。最後是一個大小為0的塊,就表示本次回應的資料發送完了。下面是一個例子。
HTTP/1.1 200 OKContent-Type: text/plainTransfer-Encoding: chunked25This is the data in the first chunk1Cand this is the second one3con8sequence0
3.5 其他功能
1.1版還新增了許多動詞方法:PUT、PATCH、HEAD、 OPTIONS、DELETE。
另外,用戶端請求的頭資訊新增了Host欄位,用來指定伺服器的網域名稱。
Host: www.example.com
有了Host欄位,就可以將請求發往同一台伺服器上的不同網站,為虛擬機器主機的興起打下了基礎。
3.6 缺點
雖然1.1版允許複用TCP串連,但是同一個TCP串連裡面,所有的資料通訊是按次序進行的。伺服器只有處理完一個回應,才會進行下一個回應。要是前面的回應特別慢,後面就會有許多請求排隊等著。這稱為"隊頭堵塞"(Head-of-line blocking)。
為了避免這個問題,只有兩種方法:一是減少請求數,二是同時多開持久串連。這導致了很多的網頁最佳化技巧,比如合并指令碼和樣式表、將圖片嵌入CSS代碼、網域名稱分區(domain sharding)等等。如果HTTP協議設計得更好一些,這些額外的工作是可以避免的。
四、SPDY 協議
2009年,Google公開了自行研發的 SPDY 協議,主要解決 HTTP/1.1 效率不高的問題。
這個協議在Chrome瀏覽器上證明可行以後,就被當作 HTTP/2 的基礎,主要特性都在 HTTP/2 之中得到繼承。
五、HTTP/2
2015年,HTTP/2 發布。它不叫 HTTP/2.0,是因為標準委員會不打算再發布子版本了,下一個新版本將是 HTTP/3。
5.1 二進位協議
HTTP/1.1 版的頭資訊肯定是文本(ASCII編碼),資料體可以是文本,也可以是二進位。HTTP/2 則是一個徹底的二進位協議,頭資訊和資料體都是二進位,並且統稱為"幀"(frame):頭資訊幀和資料幀。
二進位協議的一個好處是,可以定義額外的幀。HTTP/2 定義了近十種幀,為將來的進階應用程式打好了基礎。如果使用文本實現這種功能,解析資料將會變得非常麻煩,二進位解析則方便得多。
5.2 多工
HTTP/2 複用TCP串連,在一個串連裡,用戶端和瀏覽器都可以同時發送多個請求或回應,而且不用按照順序一一對應,這樣就避免了"隊頭堵塞"。
舉例來說,在一個TCP串連裡面,伺服器同時收到了A請求和B請求,於是先回應A請求,結果發現處理過程非常耗時,於是就發送A請求已經處理好的部分, 接著回應B請求,完成後,再發送A請求剩下的部分。
這樣雙向的、即時的通訊,就叫做多工(Multiplexing)。
5.3 資料流
因為 HTTP/2 的資料包是不按順序發送的,同一個串連裡面連續的資料包,可能屬於不同的回應。因此,必須要對資料包做標記,指出它屬於哪個回應。
HTTP/2 將每個請求或回應的所有資料包,稱為一個資料流(stream)。每個資料流都有一個獨一無二的編號。資料包發送的時候,都必須標記資料流ID,用來區分它屬於哪個資料流。另外還規定,用戶端發出的資料流,ID一律為奇數,伺服器發出的,ID為偶數。
資料流發送到一半的時候,用戶端和伺服器都可以發送訊號(RST_STREAM幀),取消這個資料流。1.1版取消資料流的唯一方法,就是關閉TCP串連。這就是說,HTTP/2 可以取消某一次請求,同時保證TCP串連還開啟著,可以被其他請求使用。
用戶端還可以指定資料流的優先順序。優先順序越高,伺服器就會越早回應。
5.4 頭資訊壓縮
HTTP 協議不帶有狀態,每次請求都必須附上所有資訊。所以,請求的很多欄位都是重複的,比如Cookie和User Agent,一模一樣的內容,每次請求都必須附帶,這會浪費很多頻寬,也影響速度。
HTTP/2 對這一點做了最佳化,引入了頭資訊壓縮機制(header compression)。一方面,頭資訊使用gzip或compress壓縮後再發送;另一方面,用戶端和伺服器同時維護一張頭資訊表,所有欄位都會存入這個表,產生一個索引號,以後就不發送同樣欄位了,只發送索引號,這樣就提高速度了。
5.5 伺服器推送
HTTP/2 允許伺服器未經請求,主動向用戶端發送資源,這叫做伺服器推送(server push)。
常見情境是用戶端請求一個網頁,這個網頁裡麵包含很多靜態資源。正常情況下,用戶端必須收到網頁後,解析HTML源碼,發現有靜態資源,再發出靜態資源請求。其實,伺服器可以預期到用戶端請求網頁後,很可能會再請求靜態資源,所以就主動把這些靜態資源隨著網頁一起發給用戶端了。
六、參考連結
- Journey to HTTP/2, by Kamran Ahmed
- HTTP, by Wikipedia
- HTTP/1.0 Specification
- HTTP/2 Specification
(完)
Http協議入門: