

在本文中,我們將簡(jiǎn)要回顧 HTTP 協(xié)議的發(fā)展歷史。對 HTTP 不同語(yǔ)義的完整討論超出了本文的范圍,但理解 HTTP 的關(guān)鍵設計變更以及每個(gè)變更背后的動(dòng)機將為我們討論 HTTP 性能提供必要的背景
-- Ilya Grigorik
譯注:本文來(lái)源于 2013 年出版的《 High Performance Browser Networking 》的第九章,因此有些信息略有過(guò)時(shí)。事實(shí)上,現在 HTTP/2 已經(jīng)有相當的不是,而新的 HTTP/3 也在設計和標準制定當中。
超文本傳輸協(xié)議(Hypertext Transfer Protocol)(HTTP)是互聯(lián)網(wǎng)上最普遍和廣泛采用的應用程序協(xié)議之一。它是客戶(hù)端和服務(wù)器之間的通用語(yǔ)言,支持現代 Web。從最初作為單個(gè)的關(guān)鍵字和文檔路徑開(kāi)始,它已成為不僅僅是瀏覽器的首選協(xié)議,而且幾乎是所有連接互聯(lián)網(wǎng)硬件和軟件應用程序的首選協(xié)議。
在本文中,我們將簡(jiǎn)要回顧 HTTP 協(xié)議的發(fā)展歷史。對 HTTP 不同語(yǔ)義的完整討論超出了本文的范圍,但理解 HTTP 的關(guān)鍵設計變更以及每個(gè)變更背后的動(dòng)機將為我們討論 HTTP 性能提供必要的背景,特別是在 HTTP/2 中即將進(jìn)行的許多改進(jìn)。
蒂姆·伯納斯·李(Tim Berners-Lee) 最初的 HTTP 提案在設計時(shí)考慮到了簡(jiǎn)單性,以幫助他采用他的另一個(gè)新想法: 萬(wàn)維網(wǎng)(World Wide Web)。這個(gè)策略看起來(lái)奏效了:注意,他是一個(gè)有抱負的協(xié)議設計者。
1991 年,伯納斯·李概述了這個(gè)新協(xié)議的動(dòng)機,并列出了幾個(gè)高級設計目標:文件傳輸功能、請求超文檔存檔索引搜索的能力,格式協(xié)商以及將客戶(hù)端引用到另一個(gè)服務(wù)器的能力。為了證明該理論的實(shí)際應用,構建了一個(gè)簡(jiǎn)單原型,它實(shí)現了所提議功能的一小部分。
客戶(hù)端請求是一個(gè) ASCII 字符串。
客戶(hù)端請求以回車(chē)符(CRLF)終止。
服務(wù)器響應是 ASCII 字符流。
服務(wù)器響應是一種超文本標記語(yǔ)言(HTML)。
文檔傳輸完成后連接終止。
然而,即使這聽(tīng)起來(lái)也比實(shí)際復雜得多。這些規則支持的是一種非常簡(jiǎn)單的,對 Telnet 友好的協(xié)議,一些 Web 服務(wù)器至今仍然支持這種協(xié)議:
$> telnet google.com 80
Connected to 74.125.xxx.xxx
GET /about/
(hypertext response)
(connection closed)
請求包含這樣一行:GET 方法和請求文檔的路徑。響應是一個(gè)超文本文檔,沒(méi)有標題或任何其他元數據,只有 HTML。真的是再簡(jiǎn)單不過(guò)了。此外,由于之前的交互是預期協(xié)議的子集,因此它獲得了一個(gè)非官方的 HTTP 0.9 標簽。其余的,就像他們所說(shuō)的,都是歷史。
從 1991 年這些不起眼的開(kāi)始,HTTP 就有了自己的生命,并在接下來(lái)幾年里迅速發(fā)展。讓我們快速回顧一下 HTTP 0.9 的特性:
采用客戶(hù)端-服務(wù)器架構,是一種請求-響應協(xié)議。
采用 ASCII 協(xié)議,運行在 TCP/IP 鏈路上。
旨在傳輸超文本文檔(HTML)。
每次請求后,服務(wù)器和客戶(hù)端之間的連接都將關(guān)閉。
流行的 Web 服務(wù)器,如 Apache 和 Nginx,仍然支持 HTTP 0.9 協(xié)議,部分原因是因為它沒(méi)有太多功能!如果你感興趣,打開(kāi) Telnet 會(huì )話(huà)并嘗試通過(guò) HTTP 0.9 訪(fǎng)問(wèn) google.com 或你最喜歡的網(wǎng)站,并檢查早期協(xié)議的行為和限制。
1991 年至 1995 年期間,HTML 規范和一種稱(chēng)為 “web 瀏覽器”的新型軟件快速發(fā)展,面向消費者的公共互聯(lián)網(wǎng)基礎設施也開(kāi)始出現并快速增長(cháng)。
完美風(fēng)暴:1990 年代初的互聯(lián)網(wǎng)熱潮
基于蒂姆·伯納斯·李最初的瀏覽器原型,美國國家超級計算機應用中心(NCSA)的一個(gè)團隊決定實(shí)現他們自己的版本。就這樣,第一個(gè)流行的瀏覽器誕生了:NCSA Mosaic。1994 年 10 月,NCSA 團隊的一名程序員 Marc Andreessen 與 Jim Clark 合作創(chuàng )建了 Mosaic Communications,該公司后來(lái)改名為 Netscape(網(wǎng)景),并于 1994 年 12 月發(fā)布了 Netscape Navigator 1.0。從這一點(diǎn)來(lái)說(shuō),已經(jīng)很清楚了,萬(wàn)維網(wǎng)已經(jīng)不僅僅是學(xué)術(shù)上的好奇心了。
實(shí)際上,同年在瑞士日內瓦組織了第一次萬(wàn)維網(wǎng)會(huì )議,這導致 萬(wàn)維網(wǎng)聯(lián)盟(World Wide Web Consortium)(W3C)的成立,以幫助指導 HTML 的發(fā)展。同樣,在 IETF 內部建立了一個(gè)并行的 HTTP 工作組(HTTP Working Group)(HTTP-WG),專(zhuān)注于改進(jìn) HTTP 協(xié)議。后來(lái)這兩個(gè)團體一直對 Web 的發(fā)展起著(zhù)重要作用。
最后,完美風(fēng)暴來(lái)臨,CompuServe,AOL 和 Prodigy 在 1994-1995 年的同一時(shí)間開(kāi)始向公眾提供撥號上網(wǎng)服務(wù)。憑借這股迅速的浪潮,Netscape 在 1995 年 8 月 9 日憑借其成功的 IPO 創(chuàng )造了歷史。這預示著(zhù)互聯(lián)網(wǎng)熱潮已經(jīng)到來(lái),人人都想分一杯羹!
不斷增長(cháng)的新 Web 所需功能及其在公共網(wǎng)站上的應用場(chǎng)景很快暴露了 HTTP 0.9 的許多基礎限制:我們需要一種能夠提供超文本文檔、提供關(guān)于請求和響應的更豐富的元數據,支持內容協(xié)商等等的協(xié)議。相應地,新興的 Web 開(kāi)發(fā)人員社區通過(guò)一個(gè)特殊的過(guò)程生成了大量實(shí)驗性的 HTTP 服務(wù)器和客戶(hù)端實(shí)現來(lái)回應:實(shí)現,部署,并查看其他人是否采用它。
從這些急速增長(cháng)的實(shí)驗開(kāi)始,一系列最佳實(shí)踐和常見(jiàn)模式開(kāi)始出現。1996 年 5 月, HTTP 工作組(HTTP Working Group)(HTTP-WG)發(fā)布了 RFC 1945,它記錄了許多被廣泛使用的 HTTP/1.0 實(shí)現的“常見(jiàn)用法”。請注意,這只是一個(gè)信息性 RFC:HTTP/1.0,如你所知的,它不是一個(gè)正式規范或 Internet 標準!
話(huà)雖如此,HTTP/1.0 請求看起來(lái)應該是:
$> telnet website.org 80
Connected to xxx.xxx.xxx.xxx
GET /rfc/rfc1945.txt HTTP/1.0 ?
User-Agent: CERN-LineMode/2.15 libwww/2.17b3
Accept: */*
HTTP/1.0 200 OK ?
Content-Type: text/plain
Content-Length: 137582
Expires: Thu, 01 Dec 1997 16:00:00 GMT
Last-Modified: Wed, 1 May 1996 12:45:26 GMT
Server: Apache 0.84
(plain-text response)
(connection closed)
? 請求行有 HTTP 版本號,后面跟請求頭
? 響應狀態(tài),后跟響應頭
前面的交互并不是 HTTP/1.0 功能的詳盡列表,但它確實(shí)說(shuō)明了一些關(guān)鍵的協(xié)議更改:
請求可能多個(gè)由換行符分隔的請求頭字段組成。
響應對象的前綴是響應狀態(tài)行。
響應對象有自己的一組由換行符分隔的響應頭字段。
響應對象不限于超文本。
每次請求后,服務(wù)器和客戶(hù)端之間的連接都將關(guān)閉。
請求頭和響應頭都保留為 ASCII 編碼,但響應對象本身可以是任何類(lèi)型:HTML 文件、純文本文件、圖像或任何其他內容類(lèi)型。因此,HTTP 的“超文本傳輸”部分在引入后不久就變成了用詞不當。實(shí)際上,HTTP 已經(jīng)迅速發(fā)展成為一種超媒體傳輸,但最初的名稱(chēng)沒(méi)有改變。
除了媒體類(lèi)型協(xié)商之外,RFC 還記錄了許多其他常用功能:內容編碼、字符集支持、多部分類(lèi)型、授權、緩存、代理行為、日期格式等。
今天,幾乎所有 Web 上的服務(wù)器都可以并且仍將使用 HTTP/1.0。不過(guò),現在你應該更加清楚了!每個(gè)請求都需要一個(gè)新的 TCP 連接,這會(huì )對 HTTP/1.0 造成嚴重的性能損失。參見(jiàn) 三次握手 ,接著(zhù)會(huì ) 慢啟動(dòng) 。
將 HTTP 轉變?yōu)楣俜?IETF 互聯(lián)網(wǎng)標準的工作與圍繞 HTTP/1.0 的文檔工作并行進(jìn)行,并計劃從 1995 年至 1999 年完成。事實(shí)上,第一個(gè)正式的 HTTP/1.1 標準定義于 RFC 2068,它在 HTTP/1.0 發(fā)布大約六個(gè)月后,即 1997 年 1 月正式發(fā)布。兩年半后,即 1999 年 6 月,一些新的改進(jìn)和更新被納入標準,并作為 RFC 2616 發(fā)布。
HTTP/1.1 標準解決了早期版本中發(fā)現的許多協(xié)議歧義,并引入了一些關(guān)鍵的性能優(yōu)化:保持連接,分塊編碼傳輸,字節范圍請求,附加緩存機制,傳輸編碼和請求管道。
有了這些功能,我們現在可以審視一下由任何現代 HTTP 瀏覽器和客戶(hù)端執行的典型 HTTP/1.1 會(huì )話(huà):
$> telnet website.org 80
Connected to xxx.xxx.xxx.xxx
GET /index.html HTTP/1.1 ?
Host: website.org
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_4)... (snip)
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
Cookie: __qca=P0-800083390... (snip)
HTTP/1.1 200 OK ?
Server: nginx/1.0.11
Connection: keep-alive
Content-Type: text/html; charset=utf-8
Via: HTTP/1.1 GWA
Date: Wed, 25 Jul 2012 20:23:35 GMT
Expires: Wed, 25 Jul 2012 20:23:35 GMT
Cache-Control: max-age=0, no-cache
Transfer-Encoding: chunked
100 ?
<!doctype html>
(snip)
100
(snip)
0 ?
GET /favicon.ico HTTP/1.1 ?
Host: www.website.org
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_4)... (snip)
Accept: */*
Referer: http://website.org/
Connection: close ?
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
Cookie: __qca=P0-800083390... (snip)
HTTP/1.1 200 OK ?
Server: nginx/1.0.11
Content-Type: image/x-icon
Content-Length: 3638
Connection: close
Last-Modified: Thu, 19 Jul 2012 17:51:44 GMT
Cache-Control: max-age=315360000
Accept-Ranges: bytes
Via: HTTP/1.1 GWA
Date: Sat, 21 Jul 2012 21:35:22 GMT
Expires: Thu, 31 Dec 2037 23:55:55 GMT
Etag: W/PSA-GAu26oXbDi
(icon data)
(connection closed)
? 請求的 HTML 文件,包括編、字符集和 cookie 元數據
? 原始 HTML 請求的分塊響應
? 以 ASCII 十六進(jìn)制數字(256 字節)表示塊中的八位元的數量
? 分塊流響應結束
? 在相同的 TCP 連接上請求一個(gè)圖標文件
? 通知服務(wù)器不再重用連接
? 圖標響應后,然后關(guān)閉連接
哇,這里發(fā)生了很多事情!第一個(gè)也是最明顯的區別是我們有兩個(gè)對象請求,一個(gè)用于 HTML 頁(yè)面,另一個(gè)用于圖像,它們都通過(guò)一個(gè)連接完成。這就是保持連接的實(shí)際應用,它允許我們重用現有的 TCP 連接到同一個(gè)主機的多個(gè)請求,提供一個(gè)更快的最終用戶(hù)體驗。參見(jiàn) TCP 優(yōu)化 。
要終止持久連接,注意第二個(gè)客戶(hù)端請求通過(guò) Connection 請求頭向服務(wù)器發(fā)送顯示的 close。類(lèi)似地,一旦傳輸響應,服務(wù)器就可以通知客戶(hù)端關(guān)閉當前 TCP 連接。從技術(shù)上講,任何一方都可以在沒(méi)有此類(lèi)信號的情況下終止 TCP 連接,但客戶(hù)端和服務(wù)器應盡可能提供此類(lèi)信號,以便雙方都啟用更好的連接重用策略。
HTTP/1.1 改變了 HTTP 協(xié)議的語(yǔ)義,默認情況下使用保持連接。這意味著(zhù),除非另有說(shuō)明(通過(guò) Connection:close 頭),否則服務(wù)器應默認保持連接打開(kāi)。
但是,同樣的功能也被反向移植到 HTTP/1.0 上,通過(guò) Connection:keep-Alive 頭啟用。因此,如果你使用 HTTP/1.1,從技術(shù)上講,你不需要 Connection:keep-Alive 頭,但許多客戶(hù)端仍然選擇提供它。
此外,HTTP/1.1 協(xié)議還添加了內容、編碼、字符集,甚至語(yǔ)言協(xié)商、傳輸編碼、緩存指令、客戶(hù)端 cookie,以及可以針對每個(gè)請求協(xié)商的十幾個(gè)其他功能。
我們不打算詳細討論每個(gè) HTTP/1.1 特性的語(yǔ)義。這個(gè)主題可以寫(xiě)一本專(zhuān)門(mén)的書(shū)了,已經(jīng)有了很多很棒的書(shū)。相反,前面的示例很好地說(shuō)明了 HTTP 的快速進(jìn)展和演變,以及每個(gè)客戶(hù)端-服務(wù)器交換的錯綜復雜的過(guò)程,里面發(fā)生了很多事情!
要了解 HTTP 協(xié)議所有內部工作原理,參考 David Gourley 和 Brian Totty 共同撰寫(xiě)的權威指南: The Definitive Guide。
RFC 2616 自發(fā)布以來(lái),已經(jīng)成為互聯(lián)網(wǎng)空前增長(cháng)的基礎:數十億各種形狀和大小的設備,從臺式電腦到我們口袋里的小型網(wǎng)絡(luò )設備,每天都在使用 HTTP 來(lái)傳送新聞,視頻,在我們生活中的數百萬(wàn)的其他網(wǎng)絡(luò )應用程序都在依靠它。
一開(kāi)始是一個(gè)簡(jiǎn)單的,用于檢索超文本的簡(jiǎn)單協(xié)議,很快演變成了一種通用的超媒體傳輸,現在十年過(guò)去了,它幾乎可以為你所能想象到的任何用例提供支持??梢允褂脜f(xié)議的服務(wù)器無(wú)處不在,客戶(hù)端也可以使用協(xié)議,這意味著(zhù)現在許多應用程序都是專(zhuān)門(mén)在 HTTP 之上設計和部署的。
需要一個(gè)協(xié)議來(lái)控制你的咖啡壺?RFC 2324 已經(jīng)涵蓋了超文本咖啡壺控制協(xié)議(HTCPCP/1.0)- 它原本是 IETF 在愚人節開(kāi)的一個(gè)玩笑,但在我們這個(gè)超鏈接的新世界中,它不僅僅意味著(zhù)一個(gè)玩笑。
超文本傳輸協(xié)議(HTTP)是一個(gè)應用程序級的協(xié)議,用于分布式、協(xié)作、超媒體信息系統。它是一種通用的、無(wú)狀態(tài)的協(xié)議,可以通過(guò)擴展請求方法、錯誤碼和頭,用于超出超文本之外的許多任務(wù),比如名稱(chēng)服務(wù)器和分布式對象管理系統。HTTP 的一個(gè)特性是數據表示的類(lèi)型和協(xié)商,允許獨立于傳輸的數據構建系統。
RFC 2616: HTTP/1.1, June 1999
HTTP 協(xié)議的簡(jiǎn)單性是它最初被采用和快速增長(cháng)的原因。事實(shí)上,現在使用 HTTP 作為主要控制和數據協(xié)議的嵌入式設備(傳感器,執行器和咖啡壺)并不罕見(jiàn)。但在其自身成功的重壓下,隨著(zhù)我們越來(lái)越多地繼續將日?;?dòng)轉移到網(wǎng)絡(luò ) —— 社交、電子郵件、新聞和視頻,以及越來(lái)越多的個(gè)人和工作空間,它也開(kāi)始顯示出壓力的跡象。用戶(hù)和 Web 開(kāi)發(fā)人員現在都要求 HTTP/1.1 提供近乎實(shí)時(shí)的響應能力和協(xié)議 性能,如果不進(jìn)行一些修改,就無(wú)法滿(mǎn)足這些要求。
為了應對這些新挑戰,HTTP 必須繼續發(fā)展,因此 HTTPbis 工作組在 2012 年初宣布了一項針對 HTTP/2 的新計劃:
已經(jīng)有一個(gè)協(xié)議中出現了新的實(shí)現經(jīng)驗和興趣,該協(xié)議保留了 HTTP 的語(yǔ)義,但是沒(méi)有保留 HTTP/1.x 的消息框架和語(yǔ)法,這些問(wèn)題已經(jīng)被確定為妨礙性能和鼓勵濫用底層傳輸。
工作組將使用有序的雙向流中生成 HTTP 當前語(yǔ)義的新表達式的規范。與 HTTP/1.x 一樣,主要傳輸目標是 TCP,但是應該可以使用其他方式傳輸。
HTTP/2 charter, January 2012
HTTP/2 的主要重點(diǎn)是提高傳輸性能并支持更低的延遲和更高的吞吐量。主要的版本增量聽(tīng)起來(lái)像是一個(gè)很大的步驟,但就性能而言,它將是一個(gè)重大的步驟,但重要的是要注意,沒(méi)有任何高級協(xié)議語(yǔ)義收到影響:所有的 HTTP 頭,值和用例是相同的。
任何現有的網(wǎng)站或應用程序都可以并且將通過(guò) HTTP/2 傳送而無(wú)需修改。你無(wú)需修改應用程序標記來(lái)利用 HTTP/2。HTTP 服務(wù)器將來(lái)一定會(huì )使用 HTTP/2,但這對大多數用戶(hù)來(lái)說(shuō)應該是透明的升級。如果工作組實(shí)現目標,唯一的區別應該是我們的應用程序以更低的延遲和更好的網(wǎng)絡(luò )連接利用率來(lái)傳送數據。
話(huà)雖如此,但我們不要走的太遠了。在討論新的 HTTP/2 協(xié)議功能之前,有必要回顧一下我們現有的 HTTP/1.1 部署和性能最佳實(shí)踐。HTTP/2 工作組正在新規范上取得快速的進(jìn)展,但即使最終標準已經(jīng)完成并準備就緒,在可預見(jiàn)的未來(lái),我們仍然必須支持舊的 HTTP/1.1 客戶(hù)端,實(shí)際上,這得十年或更長(cháng)時(shí)間。
via: https://hpbn.co/brief-history-of-http/#http-09-the-one-line-protocol
作者: Ilya Grigorik 選題: lujun9972 譯者: MjSeven 校對: wxy
本文由 LCTT 原創(chuàng )編譯, Linux中國 榮譽(yù)推出
聯(lián)系客服