萬維網:蒂姆·伯納斯·李的信息帝國
信息大爆炸
人類文明史就是一部信息史——人類如何獲取、存儲和傳遞信息的歷史。
遠古時代,人類主要通過觀察自然現象來獲取信息和知識,通過口口相傳的方式傳遞信息。
而后,人類發明了結繩、符號,可以將個人大腦中的信息加以符號化——這可以說是人類最早的信息存儲形式(它也是一種傳播形式)。這些符號不斷地傳播并豐富,最終演化為文字。
文字是個偉大的發明,它使得信息和知識能夠跨越時空傳遞。如果沒有文字,人類文明只能以“代代相傳”的方式進行。
除了口口相傳和文字,人類還發明了諸如烽火、燈塔、鼓聲等遠距離通信手段——人類對通信距離的不斷突破,到近代發明電報、無線電后,達到了一次高峰。
人類生產信息的腳步也是不斷加快。歐洲和中國在古希臘和春秋戰國時期出現了一次信息生產高峰,古希臘時期建造出了世界上最早的圖書館之一——亞歷山大圖書館。
圖書館是人類進行集中式信息管理的偉大嘗試。
歐洲文藝復興和啟蒙運動時期是人類信息生產的另一個高峰。如果說在古希臘時期,知識生產大分工只是處于萌芽階段的話(那時候哲學和科學是不分家的),文藝復興和啟蒙運動時期則正式開啟了知識生產大分工的大門。科學從哲學中獨立出來,逐步發展成今天所理解的物理學、化學、生物學、經濟學等學科。
知識生產大分工的結果是人類進入了知識生產的指數加速時代。人類現在幾十年生產出來的知識比過去一千年都要多。
過去,中國古人只需要背熟四書五經大學中庸就行了,現在光一門物理學(或者任意其他一門學科)的知識量就比那些多得多。古人可以做到“無所不知”,而二十世紀后的人類已經不可能做到這一點了——甚至不可能做到窮盡一門學科的知識。
人類知識量指數增長帶來的是信息管理問題。面對信息海洋(知識是一種信息),人們不知道該獲取哪些信息了,需要某類信息的時候也不知道該去哪里獲取了。人類面臨著信息失控的危險。
人們可以建造更大的圖書館——再大也裝不下所有的知識,而且圖書館規模越大,可能越難快速檢索到有用的信息。
人們還嘗試編纂百科全書——將那些重要的知識集中到一系列書籍中,為普通大眾在知識的海洋中提供指南和導航。中國明朝永樂年間編纂了集大成之類書《永樂大典》;啟蒙運動時期法國哲學家丹尼·狄德羅編纂了歐洲第一部大百科全書;1768 年英國人編纂了著名的《不列顛百科全書》。
百科全書同樣不可能囊括所有的知識。
萬尼瓦爾·布什與 MEMEX
計算機并不是被設計用來處理信息的。
這從計算機的名字就能看出來——Computer 原意是“計算員”,在計算機出現之前是一個專門的職業(像美國的人口普查、歐洲的航海歷之前都是由這些人類計算員手工算出來的)。
從巴貝奇的差分機和分析機,到何樂禮的電動制表機,到萬尼瓦爾·布什的微分分析儀,到第一臺通用電子計算機 ENIAC,其設計的目的無不是為了數值計算。
馮·諾依曼當初“鬼使神差”地加入莫爾學院的 ENIAC 工作小組,原因也在于尋求用計算機計算原子彈核爆問題——這一加入讓他“鬼使神差”地成了現代計算機之父。
隨著二戰結束,計算機逐漸從軍事和科研走向商業領域。
同時人們嘗試進一步挖掘計算機的計算潛力。根據圖靈的理論,通用計算機可以計算所有的可計算問題,可以無限逼近(甚至超越)人腦——這些研究我們今天叫“人工智能”,圖靈也被公認為人工智能之父。
然而,還存在另一派研究人員,他們認為計算機研究應該要為提升人類工作效率服務,而不是當前看不到實際用途的所謂的“人工智能”。
他們發現,人們在工作中通常只有 15% 的時間在“思考”,其余時間都在查閱資料、繪制圖表等,工作效率非常底下。他們希望能用計算機來處理這些低級而耗時的事務,將人類的大腦解放出來去思考更有價值的事情。
總之,這些人開始研究用計算機處理信息——這些研究最終推動人類文明走向信息化時代。
數值處理和信息處理是不同的。
數值處理關注如何求三角函數、對數、微積分等數學計算問題,主要用在軍事、科研以及商業報表領域。
信息處理關注人類社會的各種信息,諸如書籍、信函、圖片、音頻、視頻。
第一臺通用電子計算機 ENIAC 全稱是 Electronic Numerical Integrator And Computer,翻譯過來是“電子數字積分計算機”——看名字就知道人們想用它來干嘛。
計算機的兩大分支:數值處理和信息處理,在不同時期存在不同的發展態勢。二戰時,主要用來做數值處理(ENIAC 的目的是計算彈道);戰后其重心逐步轉變為信息處理上(當然不是說數值處理方面就沒有發展了),最終推動人類走向信息化時代;如今,人工智能被重新提上議程,自動駕駛、智慧城市甚是火熱。
前面說隨著人類信息量的指數增長,傳統的信息存儲和檢索方式面臨越來越大的挑戰。
首先是存儲。傳統的信息存儲方式主要是書籍、文件這些紙質媒介,這種媒介在信息量驟增的二十世紀已經相當笨重和效率低下。大學需要建造龐大的圖書館,公司需要準備大量的文件柜(不可避免地占用大量空間)歸檔各種函件。
其次是檢索。雖然有各種文件歸檔方案,在海量文件中找到想要的那個仍然是一件非常費力而又無聊的事情——一旦記不清文件放在何處更是讓人抓狂。
所以人們想能否通過計算機來解決這些問題。
1945 年,萬尼瓦爾·布什(Vannevar Bush)發表了一篇名為"As We May Think"的文章。文章描述了一種被稱為 MEMEX 的機器,實現新型的數字化的信息存儲和檢索模式。
MEMEX 設備相當于一個數字圖書館,它將現實中的各種書籍、圖片、文件等數字化并存儲在微縮膠片上,解決紙質媒介的存儲效率問題。
MEMEX有一個屏幕,資料可以投影到上面進行閱讀,還有一個鍵盤,一系列按鈕和把手。
更重要的,布什在這篇文章中提出了后來被稱為“超文本”的概念,兩個相關聯的文檔之間可以建立某種關聯使得可以從一篇文檔直接跳轉到另一篇文檔。
布什并沒有在他的文章中使用“超文本”這個詞,超文本(Hypertext)一詞是德特·納爾遜于 20 世紀 60 年代創造的。
超文本在今天看來稀疏平常,但在布什那個年代是一個非常大膽的、創新的設想。傳統的信息檢索是集中式檢索。想想我們在圖書館看書,在一本書里面看到對另一本書的引用,此時如果我們需要看被引用的那本書,就得在圖書館里面到處找。再想想我們在 Linux 命令行查看某命令的幫助文檔,當我們看到 See also 后像去看其引用的命令的細節,我們得退出去然后 man 另一個命令。這種檢索模式稱為“線性檢索”。
和傳統的線性檢索方式不同,超文本允許任何信息之間交叉引用,可以從一個文檔直接轉移到另一個文檔,且能方便地返回到源文檔。
超文本的顛覆性在于它改變了人類幾千年來的集中式樹形目錄的信息檢索方式。
超文本的概念催生了后來的萬維網。
電子郵件與阿帕網
上世紀 60 年代,計算機資源是非常昂貴的,人們就想能否將這些昂貴的計算機通過某種方式連接起來,用戶可以在一臺計算機上直接使用另一臺計算機資源,從而分攤計算和存儲成本。
1963 年,美國國防部的高級研究計劃局啟動了“阿帕網”(Advanced Research Projects Agency Network,高級研究計劃局網,簡稱 ARPANET)項目——通過將計劃局的所有計算機系統連接在一起,用戶就能使用網絡上的任何計算機設施。
阿帕網使用了存儲轉發分組交換的數據交換模式,該模式沿用至今。
存儲轉發是用來解決計算機之間的連接問題。研究員們為如何將眾多的計算機兩兩連接起來犯難。不太可能為每兩臺計算機都拉一根網線——那樣網線數量將很快變得不可控。研究員們借鑒了電報行業的做法。
19 世紀電報行業在英國飛速發展,各大城市設有眾多的電報網點。電報公司之間、以及各大城市之間如何通信成為必須解決的問題。英國在幾個主要城市設立了交換中心。電報公司之間、城市之間無需兩兩相連,大家可通過交換中心轉發電報。
交換中心內部有兩撥人員,第一撥人將發送方的電報內容記錄下來,由另一撥人通過合適的出口電報機轉發給目的地(或下一個交換中心)。
將電報記錄在案的好處是它可以充當存儲系統,如果下一個交換中心很忙,則可以將報文暫存起來,等線路空閑時再發。
這就是所謂的“存儲轉發”。
通過交換中心轉發消息,使得計算機之間無需兩兩相連;通過存儲(緩沖隊列),讓上游不會因下游繁忙而阻塞(另外在分組交換模式下,交換機是先將收到的 bit 存儲起來,直到接收到完整的分組后才會轉發)。
當然存儲轉發不是沒有缺點的,報文在到達目的地之前,需要經過多個交換中心(交換機)的存儲和拷貝,大大增加了時延。
分組交換用來解決占線問題。如果我們一次發送整個報文(可能很大),那么一方面會導致高速通信線路在一段時間內被某個用戶獨占;另外采用存儲轉發策略的交換中心需要先存儲整個報文,這會帶來巨大的存儲開銷;最后,如果消息傳送失敗,需要重傳整條報文(而不是失敗的那部分)。
所以,人們決定將整個報文切分成一個個更小的分組(Package),以分組為單位在網絡上傳輸。這樣高速線路就不會被某一個用戶的龐大消息獨占了,交換中心需要存的東西也小很多。
分組交換也不是沒有缺點的。分割成多個分組后,每個分組都必須攜帶額外元數據(首部),增加了傳輸的比特數。另外接收端也必須將分組重組成報文(消息)。
最初接入阿帕網的只是高級研究計劃局內部的計算機。很快,加利福利亞大學、猶他大學、斯坦福研究院等跟計劃局有合作關系的大學計算機也加入到該網絡。在大學校園里,一些研究生和程序員也開始將自己的主機接入其中,很快便在校園內形成一種獨特的網絡社區文化。
到 1971 年春,共有23 臺主機聯網。
1972 年,阿帕網新負責人羅伯茨在首屆國際計算機通信大會上組織了一次公開演示,向世人展示阿帕網。這次演示影響很大,越來越多的研究機構和大學開始接入阿帕網,一年后,網絡中的主機數量達到 45 臺。
4 年后,數字升到 111 臺。
從數量看,增長非常緩慢。
真正推動阿帕網發展的是電子郵件。
阿帕網最初并沒有考慮電子郵件。
1971 年,BBN 的兩位程序員為阿帕網開發了實驗性的電子郵件系統——起初他們并不認為這玩意能成什么氣候。
然而很快,電子郵件成為阿帕網中最大的流量,郵件注冊用戶導 1975 年已過千人。收發電子郵件的需求也成為推動第一批非阿帕網網絡發展的主要力量。
計算機服務商看到了電子郵件的商業價值。很多服務商開始搭建自己的計算機網絡(大多數是基于阿帕網的技術)提供電子郵件服務,形成了 70 年代的“電子郵件大戰”。
電子郵件推動了計算機網絡的發展,催生了大量基于阿帕網技術實現的、相互獨立的計算機網絡。
一個問題是,這些網絡之間無法通信(自然也無法收發郵件)。
于是人們開始考慮網際互聯問題。
當時阿帕網使用的網絡協議叫 NCP(Network Control Protocol,網絡控制協議),該協議存在諸多缺陷,其中一個問題是 NCP 僅能用于同構環境中(所有計算機都要運行相同的系統)。
人們決定開發個支持異構系統的新協議替代 NCP。
1973 年,高級研究計劃局的研究員羅伯特·卡恩和溫頓·瑟夫著手設計 TCP/IP 協議;1980年,用于“異構”網絡環境的 TCP/IP 協議研制成功;1982年,ARPANET開始采用TCP/IP協議替代 NCP 協議。
TCP/IP 協議的出現推動了計算機網絡之間的網際互聯(也就是我們今天說的互聯網),最終催生出世界上最重要的互聯網——因特網。
個人計算機與因特網
電子郵件推動了阿帕網的發展,并在商業公司的推動下形成各種計算機網絡百花齊放的局面,而這種局面最終因網際互聯的實際訴求而催生出因特網。
但因特網起初增長速度是很慢的,到 1984 年接入的主機數量也不過千臺,主要是大學、科研和一些商業機構。
真正推動因特網快速發展的,是個人計算機浪潮。
80 年代,個人計算機風起云涌,IBM、蘋果、微軟群雄逐鹿,軟硬件百花齊放,個人計算機逐步成為大眾普遍接受的電子消費品和辦公品。
大量個人計算機開始接入因特網,人們不但在網上用電子郵件交流,還開始交流整篇文檔。
很快,因特網上產生了大量沒有目錄組織的文檔——如何組織和檢索這些文檔成為一個亟待解決的問題。
人們開發了一些目錄服務軟件來解決文檔檢索問題。比如有一款叫“阿奇”的軟件,通過梳理因特網,創建一個包含所有可供下載文件的目錄,用戶直接在該軟件里面即可下載,無需關注文檔的具體位置。有些軟件還提供了根據文檔名稱模糊模糊檢索功能。
和我們今天在瀏覽器中直接點“下載”按鈕就能下載文檔不同,那個時候人們要下載某個文檔,必須先知道該文檔的精確位置。典型的操作流程如下:
張三先通過 ftp 登錄到某臺遠程主機上;
登錄上去后,進入到某個目錄;
從那個目錄下載文件;
也就是說,張三必須知道文檔所在的主機,而且能登錄這臺主機,然后要進入到相應目錄。
張三不可能知道因特網上所有文檔的精確位置。所以說,當時這種目錄服務軟件還是較好地解決了人們的痛點。
這些軟件的目錄組織形式和傳統書籍無異,也是采用集中式樹形結構目錄,文檔之間沒有直接的關系。假如用戶在一篇文檔中看到“查爾斯·巴貝奇”的名字,他想檢索查爾斯·巴貝奇的信息,就要回到目錄重新查找——他無法從當前文檔直接進入關于查爾斯·巴貝奇生平的另一篇文檔。
上面提過,早在 40 年前,萬尼瓦爾·布什就提出了超文本的概念來解決信息交叉檢索問題。
那么,能否將超文本和因特網結合起來呢?
蒂姆·伯納斯·李與萬維網
在今天看來,因特網和超文本好像天然就是在一起的,然而在上個世紀八十年代卻不是這樣。那時候超文本和因特網都是很熱門的話題(至少在學術界如此),而且超文本也開始應用于一些 CD-ROM 百科全書等消費類產品,然而,兩者是單獨發展的,沒有人真正想到能將超文本應用在因特網上。
有個叫蒂姆·伯納斯·李的英國軟件工程師最終想到了這點,他于 1989 年向歐洲核子研究中心(CERN)遞交了一份項目提案,在這份提案中,描述了今后稱為“萬維網”的雛形。
歐洲核子研究中心是在聯合國教科文組織的倡導下,由歐洲 11 個國家于 1954 年 9 月創立。作為一個國際性組織,擁有非常復雜的人員和組織結構,研究項目眾多、人員變動頻繁。在這樣一個大型組織中,如何高效地組織和檢索信息(人物信息、項目信息、各種技術檔案等)成為一個棘手的問題。
人們經常被諸如下面的問題困擾:
-
這個模塊在哪里用到了?
-
這些代碼是誰寫的?在哪里執行?
-
哪些系統依賴該設備?
另外,CERN 的人員流動很大,經常因為人員離職而導致關鍵信息丟失——多數情況下不是因為離職人員沒有存留文檔,而是因為后面的人找不到文檔了。
CERN 面臨著嚴重的信息丟失問題。
伯納斯·李進一步補充道:“在不久的將來,世界其他國家和組織也會面臨同樣的問題”。
所以,必須有一套通用的信息管理方案。
當時人們普遍使用樹形結構來組織信息。Unix 文件系統就是一個例子。當時 CERN 正在用的 CERNDOC 文檔系統也是。在這種系統中,如果一個文檔(樹的葉子節點)中引用了另一個文檔(另一個葉子節點,如我們 man 查看命令文檔時的 See also),你是無法直接打開被引用的那篇文檔的,你必須先退出當前文檔,然后從目錄開始重新檢索被引用的那篇文檔。
樹形結構并沒有表達信息之間的真實關系。比如有一篇講差分機的文章,里面提到了查爾斯·巴貝奇,該場景中,“差分機”和“查爾斯·巴貝奇”是有關聯的兩條信息,但在集中式樹形目錄中,這兩條信息是作為單獨的、毫無關聯的實體存在的,我們從目錄中看不出“差分機”和“查爾斯·巴貝奇”存在任何關聯。
在傳統的基于目錄的信息組織和檢索方式中,我們基本上只是管理了一個個孤零零的信息本身,并沒有管理信息之間的關系。
相較于樹形目錄,交叉檢索的超文本更能反映現實世界的信息組織結構,它允許人們從一條信息體直接跳轉到與之關聯的另一條信息體,而無需重新檢索目錄,這大大提高了信息的檢索效率。
超文本的概念人們四十年前就提出了,在 80 年代已經有一些實際應用,如果僅僅到此為止,伯納斯·李的這個提案也沒有什么出眾之處——不過是開發另一款超文本信息管理系統而已。
這份提案的創新之處在于,它所描繪的超文本系統并不是一個系統,而是全球范圍的系統集群。
伯納斯·李發現,如今全球已經面臨著信息大爆炸帶來的信息管理問題:人們不知道該去哪里找到有用的信息;組織機構每天都面臨著大量的信息丟失;用集中式目錄管理海量信息力不從心。
另一方面,雖然當時已經開發出一些超文本系統,但這些系統自成一體,相互之間無法實現信息互聯互通。A 系統的超文本只能鏈接到 A 系統內部的文檔,無法引用 B 系統的文檔;無論是 A 系統還是 B 系統,都無法囊括世界上所有的信息。
伯納斯·李的設想是,能否將全世界所有的系統看做一個整體的、巨大的、動態的信息存儲庫,通過超文本將這些信息連接起來?
讓超文本跨越系統邊界的限制,在地球上構成一個龐大的信息宇宙空間,這是個大膽的設想。
這個設想在當時看并非不可實現。因特網已經打破網絡邊界,能夠將全世界的計算機連接成一個整體。
那么,讓超文本插上因特網的翅膀不就能夠馳騁于系統之間了嗎?
伯納斯·李將這個基于因特網的超文本信息管理系統稱為萬維網(World Wide Web)。
萬維網的關鍵組件
URI:
由于信息分布在世界各地,首先的問題便是如何找到這些信息?
在萬維網中,所有的信息統一稱為資源。每個資源都有唯一的名字(或者叫標識)。為了讓全世界各種系統都能夠理解這些名字,資源的命名必須符合某些規范——這個規范叫統一資源標識符(Uniform Resource Identifier,簡稱 URI)。
現在萬維網基本都是用 URL(Uniform Resource Locator,統一資源定位符) 這種 URI 方案。
完整的 URL 長這樣:
<scheme>://<user>:<password>@<host>:<port>/<path>;<params>?<query>#<frag>
不過我們在 HTTP 協議應用中很少用到 user、password 和 params,所以看起來長這樣:
<scheme>://<host>:<port>/<path>?<query>#<frag>
這個 URL 格式告訴客戶端如何找尋并使用資源。scheme 告訴客戶端和服務器端(包括代理)如何解析 URL以及如何處理資源(如通過 HTTP、FTP、SMTP 等協議)。 host 說明資源在哪臺主機,port 說明由該主機上哪個端口進程來接收并處理客戶端的請求。path 指定資源在該主機上具體什么位置。如果說 host 相當于公司總機號,那么 path 則相當于分機號。frag 說明客戶端只關注整個資源的某個片段(注意該參數只對客戶端程序有效,不會傳給服務器,服務器總是返回完整的資源給客戶端)。
URL 的問題是它和資源的具體位置密切綁定,一旦資源位置變了(如換域名了,或者存放位置變了),原來的 URL 也就失效了。這相當于你的身份證只能在本省使用,出省就得換身份證。
URL 的另一個問題是不好記。URL 對美國以外的人(特別是使用表意文字的人群)不太友好。萬維網的一個設計原則是最大兼容性,為了實現這一點,URL 標準規定 URL 只能使用 7 位編碼方案的 ASCII 字符,這樣便能最大程度兼容現有的協議(如 SMTP 協議),超過 7 位的字符都會被轉義。另外,隨著資源的爆炸式增長,URL 變得越來越長。
所以人們還制定了另一種 URI 方案叫 URN(Uniform Resource Name,統一資源名),這是真正的名字(相較而言,URL 是資源的位置而不是名字),它不會隨著資源的位置變化而變化。
URN 雖然看起來更高大上,但很難普及(至少在目前以及不遠的將來)。從其目標來看(資源不會隨著位置變化而變化),就目前的因特網現狀來說,需要某種中轉設施(或叫注冊中心)去做名稱和位置的映射(類似 DNS 服務做域名到 IP 的映射),而且要將現存的大量的 URL 轉換成 URN,這是個浩大的工程,許多萬維網基礎設施需要改變。
另一方面,資源位置改變后,人們可以通過 CNAME、rewrite、HTTP 重定向等手段實現新舊 URL 的轉發,甚至對于很多 URL 來說,服務提供者可以簡單粗暴地直接廢棄也不會造成多大影響。所以對于很多公司來說,這可能并不是個急需解決的問題。
隨著網址導航網站特別是搜索引擎出現后,URL 的第二個問題(難以記憶)的問題也隨之解決了——現今人們很少直接拿 URL 去訪問網站了。
所以到目前為止,URL 的日子過得還挺滋潤的。
MIME:
客戶端定位并拿到資源后,它如何處理或使用這些資源呢?客戶端如何知道服務器返回的是圖片還是普通文本呢?
萬維網將一切都視為資源,而且還給這些資源分門別類——但這其實不是萬維網自己的創舉。早在電子郵件時代,人們為了在電子郵件中收發多媒體資源(而不僅僅是純文本),就發明了 MIME 媒體類型(Multipurpose Internet Mail Extensions,多用途互聯網郵件擴展類型),萬維網采納了該類型標準。
MIME 媒體類型采用兩層分類結構:主類型+子類型,用 / 分割。有時候可能還要帶上一些額外參數說明細節。
例如 HTTP 協議中我們常見的幾種類型:
Content-Type: text/html // html 純文本
Content-Type: text/plain // 純文本
Content-Type: image/jpeg // jpeg 格式圖片
Content-Type: video/quicktime // quicktime 格式音頻
Content-Type: application/json // json 格式數據
在 HTML 表單中我們還見過一種復合表單類型:
Content-Type: multipart/form-data;boundary=AauYd8a
它表示我們提交的表單內容由多種媒體類型組成。比如在注冊時,我們要填寫用戶基本信息,還要上傳頭像,這里就存在 text/plain 和 image/jpeg 兩種媒體類型,所以此時我們得用 multipart/form-data 來表示該 HTTP 主體是個復合類型,然后在主體中將每個類型內容都帶過去,這些類型的內容之間通過 boundary 分割(此處就是字符串 AauYd8a)。
我們用 postman 模擬注冊請求,填寫了兩個字段:字段 name 是姓名,普通文本;字段 avatar 是頭像,png 圖片。得到的 HTTP 請求報文如下:

本報文主體是由 text/plain 和 image/png 兩種媒體類型組成的復合媒體類型,兩者之間通過 HTTP 首部指定的 boundary 分割。
當然復合媒體內部還可以再放復合媒體,比如上圖中第二部分我們可以再由音頻和視頻復合,然后由本部分首部指定新的 boundary 來分割音頻和視頻內容的分隔符。
目前存在幾千個 MIME 類型,完整的類型列表可在 IANA 官網查看。
客戶端拿到資源并知道了資源類型后,如果客戶端能夠編解碼此種類型,便能夠正確處理并顯示。現今瀏覽器一般都能支持幾百種常見類型處理,而且可以通過安裝擴展(或者調起本地軟件)支持更多的媒體類型。
HTTP:
雖然 URI 本身并不限制方案(scheme),但要想將全世界的計算機組織成一個龐大的統一的超文本系統,則必須使用統一的數據傳輸協議——這個協議就叫 HTTP。
如果說萬維網是一個信息帝國,那么 HTTP 就是這個帝國的官方語言。
HTTP 協議的核心功能是讓客戶端能夠告訴服務器端它想要對資源進行做什么操作——這個能力體現在 HTTP 請求報文的起始行,如:
GET /doc.html HTTP/1.1
......
這個起始行包括三部分:操作、資源、協議版本。
HTTP 的一個創舉是將種類繁多的、亂七八糟的操作高度抽象成幾個動詞。在第一版(HTTP/0.9)中,由于人們只需要查看資源,所以只有 GET 這一個動詞。后續版本加入了 HEAD、PUT、POST、TRACE、OPTIONS、DELETE 等動詞(動詞是可擴展的)。
說下幾個常用的:
-
GET:最常用的方法,請求獲取某個資源;
-
HEAD:和 GET 類似,不過服務器只返回首部而不返回主體(Body),在客戶端不需要主體信息的時候(如僅想查看資源的元信息)能節約帶寬;
-
PUT:如其名,客戶端向服務器寫入(put)文檔(和 GET 的行為相反,類似于我們用 FTP 上傳文件)。PUT 的標準行為是用客戶端請求報文的主體內容覆蓋服務器上的整個資源(如果資源不存在,則創建);
-
POST:向服務器”輸入“數據。有時候我們并不是想創建一個新資源,而僅僅是修改或增刪該資源的一些屬性,就可以用 POST 將相關數據提交給服務器。和 PUT 不同,POST 的具體行為由服務器端決定(而 PUT 的語義已經包含了其行為);
-
DELETE:如其名,刪除資源。刪除操作的語義是確定的,但服務器端可以拒絕執行該操作(拒絕刪除某資源,或者僅僅是做資源歸檔)。
起始行的第二部分是資源。這里一般是寫本地資源路徑(在使用代理時也可能寫絕對 URL)。
第三部分說明客戶端支持的 HTTP 協議的最高版本,服務器端可據此決定返回的數據格式(如有些低版本協議客戶端不支持某些新特性)。
相應地,服務器端需響應處理結果——這個也是體現在 HTTP 響應報文的起始行,如:
HTTP/1.1 200 OK
也是由三部分構成:協議版本、處理結果狀態碼、結果描述。
HTTP 的狀態碼分成五大類:
- 100 ~ 199:信息性狀態碼,平時見到最多的可能是 101 Switching Protocols,協議升級(如 WebSocket 中就用到);
- 200 ~ 299:成功狀態碼,說明服務器端成功執行了客戶端的請求;
- 300 ~ 399:重定向狀態碼,說明要到其他地方查找資源;
- 400 ~ 499:客戶端錯誤,如未授權、請求的資源不存在;
- 500 ~ 599:服務器端錯誤,如經常遇到的 502 Bad Gateway;
HTTP 報文的第二大塊是首部。首部提供應用程序和資源的元信息,如客戶端支持的媒體類型列表、主體的媒體類型、主體長度、緩存策略等。
HTTP 首部有兩個特點(這里說的是 HTTP/1.X):
- 純文本;
- 可擴展;
我們有時會聽說 HTTP 是純文本協議,這不是說 HTTP 只能傳輸純文本(HTTP 能夠傳輸圖片、視頻等所有類型數據),而是說 HTTP 的首部是 ASCII 純文本的。比如下面的請求首部:
GET / HTTP/1.1
Host: www.baidu.com
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
......
我們能看出它是在講人話。首部是 key: value 格式的文本表示。
相應地,什么是二進制協議呢?像 IP、TCP、DNS 協議的首部那樣,采用二進制位來表示特定含義的協議,這些協議的首部往往也是固定的。
純文本首部的缺點是效率低,文本顯然比二進制形式更占空間,比如"Cache-Control:no-cache"占了 22 字節,但在二進制協議中可能只需要 4 個比特就能搞定。另外報文接收方需分割字符串首部后進行字符串比較,其效率也遠低于位操作。
但純文本首部的一大優點是擴展性很好。二進制協議一般都是固定長度首部(如 TCP、DNS),所能表達的信息有限。純文本首部一方面可以隨意增加新首部,另外對現有首部的值也可以隨意擴展——可擴展性是 HTTP 協議的一個重要原則。
這里說的是 HTTP/1。HTTP/2 是二進制協議,采用 frame 作為傳輸單元。
HTTP 報文的第三大塊是主體。主體可以是任何文本或二進制數據,HTTP 協議通過一系列首部提供了主體的相關信息,如 Content-Type 指定主體的 MIME 類型,Content-Length 指定主體的長度,Content-Encoding 指定主體的編碼方式(如 gzip 壓縮)。
早期 HTTP 并沒有 Content-Length 首部,客戶端是通過服務器端關閉連接來感知主體傳輸完畢,但有一個問題:客戶端無法知道該連接是否正常關閉的(有可能服務器端除了問題,數據發送一半的時候宕掉了)。所以后面加了 Content-Length 首部。該首部在持久連接場景下是必須的——此場景服務器端發送完報文后不會關閉 TCP 連接。
從上面三大塊我們發現,可擴展性是 HTTP 協議的一個核心設計原則。靈活的擴展能力一方面滿足了萬維網上千姿百態的資源和資源使用方式,另外也使得 HTTP 協議自身擁有良好的向后兼容性(HTTP 協議還專門有個狀態碼 101 表示協議版本協商)。
B/S 架構:
萬維網相較于傳統超文本系統的一大特點是存儲和展示分離。
萬維網的資源是分布式存儲的,存儲系統(分布在世界各地的計算機)之間采用的操作系統、軟件以及協議各不相同,這要求資源的展示不能依賴于存儲實現細節。
萬維網采取了瀏覽器/服務器架構(B/S 架構。這里說的瀏覽器是泛指實現了萬維網相關協議,能夠正確展示各種資源的終端程序)。瀏覽器負責展示資源,服務器負責存儲資源。瀏覽器不關心服務器如何處理和存儲資源,服務器只需要做兩件事情:首先,給資源取個名字(URI)并公布出來;然后,服務器將資源以合適的方式(HTTP 協議)提供給瀏覽器——如此,瀏覽器便能正確地獲取并展示該資源。

資源的展示和存儲分離在今天看來稀疏平常,其實它是一個非凡的創舉。當時在大部分系統中,信息的展示是依賴于存儲格式的,一種系統中的信息無法在另一種系統正常顯示(就好比無法在 PDF 閱讀器中打開 excel 格式文件一樣)——或者說,特定格式的信息資源必須用對應的應用程序打開。
伯納斯·李提出“瀏覽器”的概念——它是一款不關心資源存儲而只專注于資源展示的軟件。因為我們對瀏覽器過于熟悉,可能并不會被這個概念激起多少波瀾,我們不妨換個名稱叫“通用信息閱覽器”。什么意思呢?這個應用程序并不是只能打開某一種類型的資源,它(理論上)可以打開任何類型資源——這才是“資源的展示不依賴于存儲格式”的終極理念。
當然,現實中沒有哪一款瀏覽器能支持所有 MIME 媒體類型,所以存在類型協商。具體做法是瀏覽器在 HTTP 請求報文中通過 Accept 首部告訴服務器它能夠(或說希望)接收的媒體類型有哪些;服務器則在響應報文首部通過 Content-Type 告知瀏覽器自己返回的資源具體是什么媒體類型(這不代表服務器端一定是以該類型存儲資源的,參見后面“網關”一節的說明),如此,如果瀏覽器支持該媒體類型,則能夠正常解析與展示。
也就是說,只要服務器端返回的資源格式是瀏覽器支持的 MIME 類型,瀏覽器就一定能夠正確展示(而不管該資源在服務器端是怎么存儲的)。
如此,我們在終端上只需要安裝一個瀏覽器(而無需像過去那樣安裝上百個專用軟件)就能瀏覽互聯網上各種形式的信息。
這種架構使得瀏覽器成為萬維網的入口,瀏覽器因此成為各公司和創業者的爭奪焦點,在 90 年代掀起一場瀏覽器大戰,其中最著名的兩個角斗士是網景和微軟。開始的時候微軟壓根不是網景的對手,但微軟最終使用捆綁銷售策略,在 Windows 98 中免費附贈 IE 瀏覽器,據此擊敗網景。IE 從此橫著走了十幾年,還產生了一款讓開發者痛恨欲絕的釘子戶——IE6。
HTML:
在萬維網的 B/S 架構中,瀏覽器測負責資源的展示,具體來說是用一種叫 HTML 的標記語言來展示資源。
HTML 的全稱是 Hyper Text Markup Language,即超文本標記語言,由伯納斯·李和同事丹尼爾·康諾利于 1990 年設計。
在 HTML 中,通過各種標簽(tag,如a、img、div)來標記文本的結構、格式或引用。瀏覽器不但可以展示不同媒體類型的資源,還能夠在一篇文檔(或叫頁面)中組織和展示多種媒體類型的資源,這種頁面我們叫超媒體頁面。
可以通過head、body、div、p、tr、td 來管理文檔的結構。
可以通過 i、b、h1 來表達文檔的格式。
可以通過 a、img、audio、video 這些超鏈接標簽給文檔引入文本、圖片、音頻、視頻資源,這些資源有可能和當前頁面在同一個服務器上,也可能位于遙遠的另一臺服務器——萬維網的資源倉庫分布在全球各地。
隨著層疊樣式表 CSS 的出現,HTML 語言的重心逐漸轉向表達文檔的結構,而由 CSS 來負責文檔的布局和樣式。
瀏覽器隨著 HTML、CSS、JavaScript 這些前端語言的發展而愈發強大起來,從最初只能展示基本的 HTML 靜態頁面,到可以通過 CSS 控制各種炫酷的樣式和布局,到通過 JavaScript 實現動態交互,到 ajax 實現動態內容和信息流式交互。
網關:
伯納斯·李在設計萬維網時,世界上已經存在大量的信息系統,這些系統間的信息格式迥異,大多數并不符合萬維網協議標準,但萬維網不能拋棄這些既有信息。
伯納斯·李提出了網關(Gateway)的概念來解決此問題。
網關其實就是一個文檔格式轉換器:將現有的不符合萬維網標準的文檔轉換成標準文檔,然后發給客戶端。

伯納斯·李的網關模型
如上圖,瀏覽器訪問 Web 服務器(左側那個 Hypertext Server),該服務器會去訪問網關服務器(右側小的那個),網關服務器將原始文檔轉換成符合萬維網格式的文檔后返回給 Web 服務器,Web 服務器再返回給瀏覽器。這里只是增加一層網關服務器,無需修改原始文檔,也不用大面積改造 Web 服務器。
伯納斯·李這個網關概念和我們今天說的網關服務器是類似的。我們今天所說的網關主要起到協議轉換作用,它的一頭通過 HTTP 協議和瀏覽器(或者代理)通信,另一頭通過其他協議(FTP、STMP、fast-cgi 等)和其他應用程序通信。另外,今天的 Web 服務器大部分同時也是網關服務器,如 nginx:

今天的 Web 服務器網關
如圖,如今網上很大部分內容都是由應用程序動態生成的,當瀏覽器訪問 Web 服務器時,Web 服務器并不是在它本地直接找到資源并返回,而是通過諸如 fast-cgi 協議訪問后面的應用程序服務,應用程序生成相關結果返回給 Web 服務器,Web 服務器再返回給瀏覽器。對于瀏覽器來說,該過程是透明的,所以對于瀏覽器來說,它就是 Web 服務器;對于應用程序來說,它將自己返回的 fast-cgi 格式數據轉換成了 HTTP 協議格式數據,因而它是個網關——因而這種網關又叫做服務器端網關。
有了網關這層轉換,就可以基于現有的數據、現有的服務(如郵件服務)對外提供統一的 HTTP 服務,從而高效快速地接入萬維網。


浙公網安備 33010602011771號