資訊大爆炸
人類文明史就是一部資訊史——人類如何獲取、儲存和傳遞資訊的歷史。
遠古時代,人類主要通過觀察自然現象來獲取資訊和知識,通過口口相傳的方式傳遞資訊。
而後,人類發明了結繩、符號,可以將個人大腦中的資訊加以符號化——這可以說是人類最早的資訊儲存形式(它也是一種傳播形式)。這些符號不斷地傳播並豐富,最終演化為文字。
文字是個偉大的發明,它使得資訊和知識能夠跨越時空傳遞。如果沒有文字,人類文明只能以“代代相傳”的方式進行。
除了口口相傳和文字,人類還發明瞭諸如烽火、燈塔、鼓聲等遠距離通訊手段——人類對通訊距離的不斷突破,到近代發明電報、無線電後,達到了一次高峰。
人類生產資訊的腳步也是不斷加快。歐洲和中國在古希臘和春秋戰國時期出現了一次資訊生產高峰,古希臘時期建造出了世界上最早的圖書館之一——亞歷山大圖書館。
圖書館是人類進行集中式資訊管理的偉大嘗試。
歐洲文藝復興和啟蒙運動時期是人類資訊生產的另一個高峰。如果說在古希臘時期,知識生產大分工只是處於萌芽階段的話(那時候哲學和科學是不分家的),文藝復興和啟蒙運動時期則正式開啟了知識生產大分工的大門。科學從哲學中獨立出來,逐步發展成今天所理解的物理學、化學、生物學、經濟學等學科。
知識生產大分工的結果是人類進入了知識生產的指數加速時代。人類現在幾十年生產出來的知識比過去一千年都要多。
過去,中國古人只需要背熟四書五經大學中庸就行了,現在光一門物理學(或者任意其他一門學科)的知識量就比那些多得多。古人可以做到“無所不知”,而二十世紀後的人類已經不可能做到這一點了——甚至不可能做到窮盡一門學科的知識。
人類知識量指數增長帶來的是資訊管理問題。面對資訊海洋(知識是一種資訊),人們不知道該獲取哪些資訊了,需要某類資訊的時候也不知道該去哪裡獲取了。人類面臨著資訊失控的危險。
人們可以建造更大的圖書館——再大也裝不下所有的知識,而且圖書館規模越大,可能越難快速檢索到有用的資訊。
人們還嘗試編纂百科全書——將那些重要的知識集中到一系列書籍中,為普通大眾在知識的海洋中提供指南和導航。中國明朝永樂年間編纂了集大成之類書《永樂大典》;啟蒙運動時期法國哲學家丹尼·狄德羅編纂了歐洲第一部大百科全書;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 服務,從而高效快速地接入全球資訊網。