Web技術(一):簡史與技術要素(URL + HTML + HTTP)

前言

你知道當我們在網頁瀏覽器( Web browser )的地址欄中輸入網址( URL: Uniform Resource Locator )時, Web 頁面是如何呈現的嗎?(下圖摘自文章:30 張圖解 HTTP 常見的面試題
Web瀏覽器訪問網頁
Web 頁面當然不能憑空顯示出來,根據 Web 瀏覽器地址欄中指定的URL,Web 瀏覽器從 Web 服務器端獲取文件資源(resource)等信息,從而顯示出 Web 頁面。像這種通過發送請求獲取服務器資源的一方(比如 Chrome、Internet Explorer、Firefox 等),都可稱爲客戶端(client);響應Web 客戶端請求,並提供資源的一方(比如 Apache、Nginx、IIS 等),都可稱爲服務器端(server)。Web客戶端向服務器請求資源,Web服務器響應資源的過程如下:
Web瀏覽器請求服務器響應過程

一、Web技術簡史

1982年,美國國防部宣佈TCP/IP爲所有軍用計算機聯網的標準,並將TCP/IP協議部署到ARPANET中。1989 年 ,加州大學伯克利分校同意將爲BSD UNIX開發的 TCP/IP 代碼納入公共領域,包括 IBM 在內的各種企業供應商在商業 TCP/IP 軟件版本中包含此代碼,這進一步推動了 TCP/IP 的傳播。

1989年初,CERN(歐洲粒子物理研究所)中由 Tim Berners-Lee 領導的小組提交了一個針對 Internet 的新協議和一個使用該協議的文檔系統,該小組將這個新系統命名爲Word Wide Web(又被稱爲“WWW”、“W3”,中文名字爲“萬維網”、"環球網"等,常簡稱爲Web),它的目的在於使全球的科學家能夠利用 Internet 交流自己的工作文檔,從而讓遠隔兩地的研究者們共享知識。這個新系統被設計爲允許 Internet 上任意一個用戶都可以從許多文檔服務計算機的數據庫中搜索和獲取文檔,而且多個文檔之間可通過超鏈接相互關聯形成超文本(HyperText),最終連成可相互參閱的 WWW(World Wide Web,萬維網)。

1990年底,Tim Berners-Lee 領導的小組已經構建了工作網絡所需的所有工具:超文本傳輸協議(HTTP);超文本標記語言(HTML);第一個Web瀏覽器(名爲WorldWideWeb,也是一個網頁編輯器);第一個HTTP服務器軟件(後來稱爲CERN httpd);第一個Web服務器主機(http://info.cern.ch)以及描述項目本身的第一個網頁。第二年 Word Wide Web 系統被移植到了其他計算機平臺並投入使用,Web技術的五大要素:HTML、HTTP、URL、Web瀏覽器、Web服務器,就此發明問世。1994年,Tim Berners-Lee決定成立萬維網聯盟(W3C),通過標準化流程來規範相關技術(HTTP、HTML等)的進一步發展。

  • URL(Uniform Resource Locator):解決了文檔的命名和尋址識別問題;
  • HTTP(HyperText Transfer Protocol):解決了瀏覽器與服務器應用層之間的交流問題;
  • HTML(HyperText Markup Language):定義了超文本文檔的表示格式;
  • Web瀏覽器:用於向服務器發起請求,並且解析收到的文檔;
  • Web服務器:用於保存文檔,並且響應來自瀏覽器的請求。

1.1 Web瀏覽器技術簡史

1993 年,現代瀏覽器的祖先 NCSA(National Center for Supercomputer Applications,美國國家超級計算機應用中心)研發的Mosaic 問世了,1994年大家熟知的網景瀏覽器Netscape Navigator 1.0發佈了,第二年Internet Explorer 1.0也發佈了,由此進入Web互聯網時代。(下圖取自:網絡的演變
瀏覽器技術發展
Web客戶端的主要任務是展現信息內容,而HTML語言則是信息展現的最有效載體之一。1990年,Tim Berners-Lee領導的小組構建的HTML 1.0超文本標記語言是繼承自SGML(Standard Generalized Markup Language)標準通用標記語言的,可以實現文本與文本之間通過超鏈接相互關聯(這種通過超鏈接實現文本關聯的技術稱爲超文本技術),由於SGML過於複雜且不利於信息的傳遞和解析,Tim Berners-Lee對其進行了大刀闊斧的簡化和完善,一種爲Web量身定製的語言 HTML 就誕生了。

最初的HTML語言只能在瀏覽器中展現靜態的文本或圖像信息,這滿足不了人們對信息豐富性和多樣性的強烈需求,於是由靜態技術向動態技術的轉變成爲了Web客戶端技術演進的永恆定律。1996年,著名的Netscape瀏覽器在其2.0版中增加了對JavaScript的支持,Microsoft的IE 3.0也在這一年開始支持Java技術,喜歡動畫、交互操作、客戶端應用的開發人員可以用Java或JavaScript語言隨心所欲地豐富HTML頁面的功能了。

真正讓HTML頁面又酷又炫、動感無限的是CSS(Cascading Style Sheets)技術。1996年底,W3C提出了CSS的建議標準,隨後 IE 3.0 和Netscape 4.0 引入了對CSS的支持,CSS大大提高了開發者對信息展現格式的控制能力,讓HTML頁面中的各種要素"活動"了起來。

1.2 Web服務器技術簡史

1993年,同瀏覽器NCSA Mosaic一起問世的還有對應的服務器NCSA httpd,緊隨其後的是現在已然成爲 Web 服務器標準之一的Apache(Apache httpd),當時它以 Apache 0.2 的姿態出現在世人眼前,到目前依然是全球最受歡迎的Web服務器軟件。微軟的 IIS (Internet Information Services)也是最早出現的Web服務器軟件之一,其早期使用的是Gopher通信協議,直到IIS 5.0版本才切換爲HTTP通信協議,隨後成爲全球第二大最受歡迎的Web服務器軟件,但從2014年開始被新晉的Nginx反超且差距越拉越大。截止到2020年,主流Web瀏覽器與Web服務器軟件的市場佔有率對比如下:
Web客戶端與服務器市場份額
最早的Web服務器簡單地響應瀏覽器發來的HTTP請求,並將存儲在服務器上的HTML文件返回給瀏覽器,此時Web服務器只能提供靜態文本或圖片的共享服務。可隨着 Web 越來越普及,僅靠這樣的做法已不足以應對所有的需求,更需要引入由程序創建 HTML 內容的做法。第一種真正使服務器能根據運行時的具體情況,動態生成HTML頁面的技術是大名鼎鼎的CGI(Common Gateway Interface)技術,CGI 1.0的標準草案於1993年由NCSA提出。

CGI定義了Web服務器與應用程序間通信的接口標準,使Web服務器可以通過CGI程序執行Web應用程序,完成動態請求的處理,然後拼接成HTML代碼返回給Web服務器,最後再將生成的HTML代碼響應給Web瀏覽器。CGI程序通過環境變量和標準輸入獲得請求的各種參數信息,通過標準輸出返回應答;服務器並不關心CGI程序是用什麼語言編寫的,它僅通過環境變量和標準輸入、輸出與CGI程序交互。
CGI
每當有一個請求對應到一個CGI程序時,服務器就啓動一個進程執行這個CGI程序,因此CGI程序對主機的資源消耗比較大(想想如果有1000個併發請求會怎麼樣),同時它的響應速度也會比較慢(進程的啓動比較花時間)。所以人們開始尋找CGI的替代者,這導致了FastCGI技術的出現。簡單來說,FastCGI本質上就是一個常駐內存的進程池技術,由調度器負責將傳遞過來的CGI請求發送給處理CGI的handler進程來處理,在一個請求處理完成之後,該處理進程不銷燬,繼續等待下一個請求的到來。

1994年,Rasmus Lerdorf發明了專用於Web服務端編程的PHP(Personal Home Page Tools)語言,與以往的CGI程序不同,PHP可以把程序嵌入到HTML代碼中去執行,不僅能更好的組織Web應用的內容,而且執行效率比外部程序更高,Web應用的開發者可以用一種更加簡便、快捷的方式實現動態Web功能。

1996年,Microsoft借鑑PHP的思想,在其Web服務器IIS 3.0中引入了ASP(Active Server Pages)技術(使用的腳本語言是VBScript和JavaScript),並於2002年被ASP.NET取代。1997年,以Sun公司爲首的Java陣營發佈了Servlet技術,第二年JSP(Java Server Pages)技術誕生,Servlet和JSP的組合(還可以加上JavaBean技術)讓Java開發者同時擁有了類似CGI程序的集中處理功能和類似PHP的HTML嵌入功能,Java的運行時編譯技術也大大提高了Servlet和JSP的執行效率。隨着Web服務器端動態頁面技術的普及,社交網絡、論壇、電子商務、信息查詢、全文檢索等各式各樣的Web應用蓬勃興起,人們終於可以享受到信息檢索、信息交換、信息處理等更爲便捷的信息服務了,萬維網也開始快速發展。
Servlet與CGI對比
Servlet程序與CGI程序的明顯不同就是:

  • Servlet 運行在與 Web 服務器程序相同的進程中(Servlet 的運行環境叫做 Web 容器或 Servlet 容器),Servlet 常駐內存,在每次請求時可從線程池啓動相對進程級別更爲輕量的線程,程序的執行效率從而變得更高;
  • CGI 運行在與 Web 服務器程序不同的進程中,每次請求啓動一個新的CGI 進程,即便是改進後的FastCGI 常駐內存,程序的執行效率依然跟Servlet 有不小的差距。

服務器端網頁動態交互功能的不斷豐富,伴隨的是代碼邏輯的複雜度快速上升,同時Web客戶端形態越來越多樣(比如手機、平板、電腦、智能電視等),Web應用需要提供的服務越來越複雜,Web應用中的網頁視圖表現模塊與業務數據處理模塊逐漸分離,向着高內聚、松耦合的方向發展。爲了更好的管理前後端代碼邏輯,出現了大量的MVC(Model–View–Controller)開發框架:

  • View:向控制器提交數據和爲模型提供數據顯示,側重於數據的可視化呈現效果;
  • Model:用於存取數據以及處理用戶請求的業務邏輯;
  • Controller:根據視圖提出的請求判斷將請求和數據交給哪個模型處理,將處理後的有關結果交給哪個視圖更新顯示;

基於 Servlet 的 MVC 模式流程
MVC框架在一定程度上實現了數據顯示與數據處理的分離,前端可以針對不同的Web客戶端形態開發不同的View視圖模板,後端可以針對不同的業務類型開發不同的 Model 數據模型,中間由Controller 完成兩部分之間的數據轉交與匹配。但MVC框架中的View與Model並沒有完全分離,二者之間仍有相當的耦合,不利於更復雜代碼邏輯的開發。隨後出現的MVP(Model–View–Presenter)框架初步實現了View與Model的完全分離,但Presenter 比原來的Controller 代碼邏輯更加複雜;MVVM(Model-View-ViewModel)框架採用事件監聽與數據雙向綁定的方法,簡化了ViewModel 與 View 的交互邏輯,不僅實現了View 與Model 的完全分離,而且提高了 View 與Model 之間的數據同步效率。
MVC/MVP/MVVM框架對比
Web最初的設計理念就是信息的共享,從Web 1.0 信息的靜態單向呈現到Web 2.0 信息的動態雙向交互,Web信息的流動和處理效率越來越高。我們設想一下,Web未來會是什麼形態呢?W3C已經明確告訴我們,Web的未來是語義化的Web(Semantic Web)。今天的Web可以自如地生成、傳遞和展現各式各樣的信息,但它還只是一個信息的"容器",很難揭示出信息本身的內容和特性。與此相對的是,未來的語義化Web 3.0是一種懂得信息內容的Web,是真正的"信息管理員"。

二、Web三大構建技術

2.1 URL / URI

網絡資源是如何唯一標識自身的呢?還記得前面介紹TCP/IP協議時,每個IP地址或域名標識Internet上唯一的一個主機,我們計算機中每個文件都是被文件系統管理的,有一個唯一的文件路徑,將某主機域名與某資源所在該主機的文件路徑連起來不就可以唯一標識並定位該資源在Internet上的存儲位置了嗎?統一資源定位符URL也正是按照這個邏輯標識某特定資源的,語法關係與標識格式(在RFC 3986中定義)如下:
URL語法關係圖
URL格式

字段名 功能描述
協議名 可以是http、https、ftp等,不區分大小寫
登錄認證信息 從服務器獲取資源需要的身份權限信息,該字段爲可選項
服務器地址 可以是IPv4、IPv6、DNS可解析的域名等,用來標識Internet上唯一的服務器主機
服務器端口號 指定服務器連接的網絡端口號,http協議默認端口號80,https協議默認端口號443
帶層次的文件路徑 指定服務器上的文件路徑來定位特指的資源,與 Linux的文件目錄結構相似
查詢字符串 針對已指定的文件路徑內的資源,可以使用查詢字符串傳入任意參數,爲可選項
片段標識符 可標記出已獲取資源中的子資源(文檔內的某個位置),該字段爲可選項

我們還經常聽到URI(Uniform Resource Identifier,統一資源標識符),它和URL是一樣的嗎?實際上URI 可以看作URL的超集,也即URL是URI 的子集,二者的關係如下:
URI與URL關係
這裏又出來一個URN(Universal Resource Name,統一資源名稱),這又是什麼呢?我們使用的身份證號,購買圖書的ISBN編號等可以唯一標識一個物體的名稱都是URN。

URI、URL、URN三者的對比如下表所示(參考博客:標識互聯網上的資源分清 URI、URL 和 URN):

名稱 功能描述 示例
URI 用來標識抽象或物理資源的一個緊湊字符串 https://developer.mozilla.org/en-US/docs/Learn
tel:+1-816-555-1212
[email protected]:mdn/browser-compat-data.git
ftp://example.org/resource.txt
urn:isbn:9780141036144
URL 一種定位資源的主要訪問機制的字符串,
唯一標識並定位該資源在Internet上的存儲位置
https://developer.mozilla.org
https://developer.mozilla.org/en-US/docs/Learn/
https://developer.mozilla.org/en-US/search?q=URL
URN 通過特定命名空間中的唯一名稱或ID來標識資源,
但不包括訪問該資源的位置或方式
urn:isbn:9780141036144
urn:ietf:rfc:7230

就像Linux一切皆文件的思想一樣,Web網絡上一切皆資源,比如文本html / xml / json、圖片jpeg / png / gif、音視頻avi / wav / mpeg、壓縮文件gz / tar / zip、二進制文件 等(可以參考MIME 資源類型),URL就可以唯一標識並定位某資源存儲的位置,以便對該資源進行增、刪、改、查等操作。

2.2 HTML / XML

前面談到Web最初的設計理念就是藉助多文檔之間相互關聯形成的超文本(HyperText),連成可相互參閱的 World Wide Web 。文檔之間如何關聯呢?超文本又是什麼呢?

有了前面URL 統一資源定位符的概念,就可以使用URL 來定位並找到某一資源(比如文檔)了,如果我們把文檔A的URL 放到文檔B中,就相當於文檔A被關聯到文檔B中了,也即通過文檔B中保存的文檔A的URL(也稱爲文檔A的超鏈接)就可以找到並訪問文檔A。如果每個文檔中都保存了多個相關文檔的URL,就可以通過URL以超鏈接的形式將相關文檔關聯起來,形成一張信息網,這種包含其它文本URL的文本稱爲超文本(HyperText)。

我們通過Web瀏覽器看到的一個個網頁實際上就是一個個超文本,Tim Berners-Lee在設計Word Wide Web時,爲了描述網頁的結構,開發的HTML(HyperText Markup Language)是一種在Web 瀏覽器中顯示超文本頁面的標準標記語言。HTML最初是用來描述多文檔之間相互關聯形成的超文本結構,隨着圖像、音頻、視頻、動畫等多媒體資源的普及,逐漸擴展爲用來描述多媒體資源之間相互關聯形成的超媒體結構(URL也可標識並定位任意多媒體資源)。

Tim Berners-Lee開發的初版HTML並沒有形成規範,後於1993年發表的第一個HTML規範提案(HTML 1.0)也因爲很多地方模糊不清而沒有被採用。1995年,由 IETF(Internet Engineering Task Force)發佈的HTML 2.0纔算是第一個HTML正式規範被普及應用(最初定義在RFC1866中,最近更新在RFC2070中)。隨後,Tim Berners-Lee牽頭成立的W3C萬維網聯合會取代IETF的角色,成爲HTML標準的制定者,並先後於1997年發佈HTML 3.2版本和HTML 4.0版本,於1999年發佈了HTML 4.01版本,該版本在很長時間內被普及應用。

如果說HTML語言給Web世界賦予了無限生機的話,那麼,XML語言的出現大概就可以算成是Web的一次新生了。按照Tim Berners-Lee的說法,Web是一個"信息空間"。HTML語言具有較強的表現力,但也存在結構過於靈活、語法不規範的弱點。當信息都以HTML語言的面貌出現時,Web這個信息空間是雜亂無章、沒有秩序的。爲了讓Web世界裏的所有信息都有章可循、有法可依,我們需要一種更爲規範、更能夠體現信息特點的語言。

1996年,W3C在SGML語言的基礎上,提出了XML(eXtensible Markup Language)語言草案,並於1998年正式發佈了XML 1.0標準。XML語言對信息的格式和表達方法做了最大程度的規範,應用軟件可以按照統一的方式處理所有XML信息。這樣一來,信息在整個Web世界裏的共享和交換就有了技術上的保障,HTML語言關心的是信息的表現形式,而XML語言關心的是信息本身的格式和數據內容。從這個意義上說,XML語言不但可以將客戶端的信息展現技術提高到一個新的層次,而且可以顯著提高服務端的信息獲取、生成、發佈和共享能力。爲了將XML信息轉換爲HTML等不同的信息展現形式,W3C於1999年制定出了XSLT(eXtensible Stylesheet Language Transformations)標準,IE 5.0在同一年就增加了對XML和XSLT的支持。

由於HTML是一種鬆散的、不能夠適應社會發展需要的標記語言,因此W3C組織在2000年,以XML爲根本重構了HTML 4.01,取名爲:XHTML(eXtensible HyperText Markup Language) 1.0。XHTML 1.0相比HTML 4.0.1並沒有引入任何新標籤或屬性,唯一的區別是語法,HTML 對語法比較隨便,而 XHTML 則要求 XML 般的嚴格語法。自此,W3C 逐漸將未來發展的重心放到XHTML 2.0上,希望將 Web 帶向 XML 的光明未來。雖然 XHTML 2 聽上去和 XHTML 1 類似,它們卻有很多差別,XHTML 2 不向前兼容,甚至不兼容之前的 HTML,這對於Web服務提供商實在是一場災難。

W3C 閉門造車的作風引起了一些人的不滿,Mozilla、Opera和Apple在 2004 年,爲了開發與現有瀏覽器向後兼容的技術,成立了WHATWG(Web Hypertext Application Technology Working Group),開始制定Web Forms 2.0 和 Web Apps 1.0標準,這兩個規範後來被合併到HTML 5標準中。2006年,Tim Berners-Lee 表示從 HTML 走向 XML 的路是行不通的,隨後W3C組建了一個新的HTML工作組,並選擇WHATWG 的成果作爲基礎,和WHATWG一同制定HTML 5的標準規範。 2008年,HTML 5第一份正式草案公佈,各大瀏覽器廠商(WHATWG成員,包括後加入的Google和Microsoft)從第一份草案就開始伴隨HTML 5的完善過程逐步增加對其新特性的支持,直到2014年,HTML 5正式標準規範才最終制定完成併發布。

HTML 5被設計爲跨平臺的,可以在不同類型的硬件(PC、平板、手機、電視機等等)上運行,並且擁有新的語義、圖形以及多媒體元素(比如video、audio和canvas 等),可以承載豐富的 web 內容而無需額外插件。HTML 5提供的新元素和新的 API 簡化了 web 應用程序的搭建,可以真正改變用戶與文檔的交互方式,這些特性是XHTML不能滿足的(HTML 5支持XHTML 1.0的嚴格語法),伴隨移動互聯網的快速發展,HTML 5目前已成爲HTML技術的主流標準。
HTML與XML對比
什麼是標記語言呢?下面以主流的HTML 5語法,展示HTML標記語言的基本結構:

<!DOCTYPE html>
<html>
 <head>
   <meta charset="utf-8">
   <title>你好</title>
 </head>
 <body>
   <p>你好,HTML!</p>
 </body>
</html>

標記語言(Markup Language)用一套“標記”來“註釋”(annotate)普通文本,對HTML來說,這套標記就是各種標籤(tag),比如上面被左右尖括號<和>括起來的部分。瀏覽器理解這套標籤的含義,並據此解讀HTML文檔,瀏覽器對HTML文檔進行解析後得到一個抽象數據結構:DOM(Document Object Model),以上面的HTML文檔爲例,它對應的DOM樹是:
HTML DOM樹
其中:

  • 根節點document:代表整個HTML文檔;
  • DOCTYPE html:文檔類型聲明(Document Type Declaration),上例聲明的文檔類型是HTML 5;
  • 每個HTML標籤,如html、head、meta等,都對應着一個節點 — 這類節點稱爲元素(Element);
  • 標籤的每個屬性都對應着它的一個子節點,比如 meta標籤的charset屬性對應着meta元素的一個子節點,這類節點稱爲屬性(Attribute)節點;
  • 標籤包含的文字對應着它的一個子節點,比如 p標籤包含的文字“你好,HTML!”對應着p元素的一個子節點,這類節點稱爲文字(Text)節點;
  • 標籤直接包含的每個標籤都對應着它的一個子節點,比如 html標籤包含的 head標籤和 body標籤,分別對應着html元素的兩個子節點head和body。

HTML支持的主要標籤如下(圖片取自博客:HTML思維導圖):
HTML主要標籤
隨着HTML標籤和屬性的豐富,HTML的樣式代碼逐漸被分離出來形成了CSS層疊樣式表,HTML樣式代碼與內容代碼分離後,HTML代碼僅含有網頁的“內容”(如文本和圖片),而CSS指定了這些內容的視覺效果。同樣的,HTML負責動態行爲的代碼也逐漸被分離出來作爲單獨的JavaScript 腳本,內容(HTML)、樣式(CSS)和行爲(JavaScript)彼此獨立又相互關聯,共同在Web頁面上展現出更加動感酷炫的多媒體信息。下面給出一個簡單的示例,在一個文件夾內分別創建三個文件:hello.html、hello.css、hello.js,這三個文件的代碼分別如下:

hello.html代碼:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>你好</title>
    <link rel="stylesheet" href="hello.css">
  </head>
  <body>
    <p>你好,HTML!</p>
    <button id="btn1">點我</button>
    <script src="hello.js"></script>
  </body>
</html>

hello.css代碼:

p{
    color: blue;
    font-size: 2em;
}

hello.js代碼:

var btn = document.getElementById('btn1');
btn.onclick = function() {
  document.body.innerHTML = '<h1>你好,JavaScript!</h1>';
};

在hello.html代碼中,通過link標籤屬性關聯hello.css代碼,通過script標籤屬性關聯hello.js代碼,用瀏覽器打開hello.html文件即可看到hello.html代碼中定義的內容、hello.css代碼中定義的樣式、hello.js代碼中定義的動作/行爲,hello.js代碼中對hello.html的訪問主要是通過DOM方法完成的。

2.3 HTTP / HTTPS

有了Web客戶端可以解讀並呈現信息的HTML文檔,也知道了該HTML頁面的URL,Web客戶端怎麼通過 Internet 從Web服務器獲取該頁面資源呢?還記得TCP/IP經典的分層模型嗎?
Web通信數據流
Web 使用一種名爲 HTTP(HyperText Transfer Protocol,超文本傳輸協議)的應用層協議作爲規範,藉助底層的TCP/IP協議完成客戶端與服務器端之間各種資源的傳輸,可以說Web 是建立在 HTTP 協議上通信的。

HTTP/1.0協議標準被正式公佈是在 1996 年,並記載於 RFC1945。Tim Berners-Lee 於1990年實現的HTTP協議並沒有作爲正式標準被建立,將其稱爲HTTP/0.9(只實現了GET方法),意爲HTTP/1.0之前的版本。

HTTP/1.0協議作爲第一版正式標準,只實現了基本的功能,通信效率比較低。於是在第二年(1997年)又發佈了HTTP/1.1 協議標準,提高了 HTTP/1.0 的傳輸效率,同時擴展了部分功能。直到今天,HTTP/1.1 仍是主流的協議版本(當初的標準是 RFC2068,之後發佈了修訂版 RFC2616)。HTTP/1.1 相比 HTTP/1.0 的改進主要有以下幾個方面:

  • 引入了持久連接( persistent connection):即TCP連接默認不關閉,可以被多個請求複用,不用聲明Connection: keep-alive;
  • 引入了管道機制( pipelining):即在同一個TCP連接裏,客戶端可以同時發送多個請求,進一步改進了HTTP協議的效率;
  • 新增請求方法:OPTIONS、PUT、PATCH、DELETE、TRACE 和 CONNECT 方法;
  • 新增首部字段:比如Host字段支持一臺主機上配置多個虛擬主機,Range字段支持請求部分頁面內容等。

HTTP是無連接協議,Web客戶端與Web服務器之間的連接由TCP協議負責管理,HTTP/1.0每次HTTP請求/響應都需要打開/關閉一次TCP連接,HTTP/1.1則可以在每次TCP連接期間完成多次HTTP請求/響應;而且多個HTTP請求可以以流水線形式發送,並不需要等收到對應的響應再發送下一個請求。持久連接與管線化
Web客戶端雖然支持以流水線形式連續發送多個HTTP請求,但Web服務端對收到的多個HTTP請求仍然是按順序處理的,假如前面有一個HTTP請求因爲某種原因被阻塞了,後面排隊的所有請求也會一同被阻塞,這會導致Web客戶端一直請求不到數據,造成“隊頭阻塞”。

HTTP也是無狀態協議,它不對之前發生過的請求和響應的狀態進行管理,也即無法根據之前的狀態進行本次的請求處理。無狀態的優點是簡單快速,減少服務器資源消耗;缺點就是對於要求登錄認證的Web頁面(比如個人博客、網銀賬戶等)無法進行狀態管理,每次跳轉到新頁面都需要再次登錄,或在請求報文中附件參數來管理登錄狀態。爲了更方便進行狀態管理,引入了Cookie技術,通過在請求和響應報文中寫入 Cookie 信息來管理客戶端的登錄狀態。
HTTP Cookie管理登錄狀態
TCP/IP協議每一層都有自己的數據幀或數據報格式,HTTP協議也不例外。由於HTTP協議基於Client/Server(或Browser/Server)結構,HTTP的報文也分爲兩種:客戶端向服務器發送HTTP請求報文;服務器向客戶端返回HTTP響應報文。下面以目前主流使用的HTTP/1.1爲例分別展示HTTP請求報文與響應報文的結構:
HTTP請求與應答報文格式
HTTP 請求報文包括請求行、請求頭部、空行、報文主體等部分構成,請求行包括請求方法、URL、協議版本三部分,請求首部主要包括請求的各種條件或屬性,空行是爲了分割首部與主體,報文主體則包含應被髮送的數據(html文檔)。HTTP響應報文包括狀態行、響應頭部、空行、報文主體等部分構成,響應行包括協議版本、狀態碼、狀態原因短語三部分,響應頭部主要包括響應的各種條件或屬性,空行用於分割首部和主體,報文主體則包含應被髮送的數據(html文檔)。

HTTP請求—響應的過程可以通過 curl 命令展示,比如在cmd命令行窗口輸入"curl -v http://www.baidu.com/index.html",返回結果如下:

C:\Users\Administrator>curl -v http://www.baidu.com/index.html
*   Trying 61.135.169.125...
* TCP_NODELAY set
* Connected to www.baidu.com (61.135.169.125) port 80 (#0)
> GET /index.html HTTP/1.1
> Host: www.baidu.com
> User-Agent: curl/7.55.1
> Accept: */*
>
< HTTP/1.1 200 OK
< Accept-Ranges: bytes
< Cache-Control: private, no-cache, no-store, proxy-revalidate, no-transform
< Connection: keep-alive
< Content-Length: 2381
< Content-Type: text/html
< Date: Mon, 27 Apr 2020 03:34:17 GMT
< Etag: "588604c4-94d"
< Last-Modified: Mon, 23 Jan 2017 13:27:32 GMT
< Pragma: no-cache
< Server: bfe/1.0.8.18
< Set-Cookie: BDORZ=27315; max-age=86400; domain=.baidu.com; path=/
<
<!DOCTYPE html>
<!--STATUS OK-->
<html>
......
</html>
* Connection #0 to host www.baidu.com left intact

其中,“> ”開頭的行是客戶端發出的請求,“< ”開頭的行是服務器的應答(應答的主體部分,也即html頁面內容,使用“…”表示了)。“* ”開頭的行是HTTP連接建立以前curl輸出的一些診斷信息,我們可以看到curl通過DNS查找到“www.baidu.com”對應的IP:61.135.169.125,port:80。

HTTP請求最常用的方法是GET和POST,上面的示例是使用GET方法請求百度首頁信息,通信協議版本爲HTTP/1.1,URL爲"/index.html" (資源在特定主機內的存儲路徑,需要與請求頭部Host字段的主機名配合使用)。請求頭部User-Agent字段爲請求客戶端名稱,Accept字段爲請求客戶端可接收並解析的資源類型。

  • GET方法:請求指定的頁面資源,頁面信息包含在返回的應答報文主體中;
  • POST方法:向指定資源提交數據進行處理請求(例如提交表單或者上傳文件),數據被包含在請求報文主體中。

上例中HTTP響應報文的響應狀態碼200表示資源請求成功,響應頭的Connection字段值keep-alive意爲持久連接,Content-Type字段值text/html表示返回的資源是html文本類型,Content-Length字段則表示文本長度(單位bytes),字段Set-Cookie則是服務器生成並添加的Cookie信息(方便管理客戶端的登錄/認證狀態),最後的應答報文主體則是請求的html頁面內容。

HTTP 協議比較簡單,數據是以明文形式傳輸的,這就存在信息泄露、信息篡改、信息僞造等風險,比如我們登錄網銀賬號時,肯定需要對傳輸的信息進行加密處理。我們留心地址欄的話也會發現,對於需要登陸的網站一般都以 https 開頭(而且有一把瑣的標識),這個https協議相比http協議增加了信息加密層 SSL/TLS,二者的協議分層結構對比如下:
HTTP協議與HTTPS協議
HTTPS 協議新增的SSL/TLS層具有信息加密、身份認證、信息完整性校驗等功能,可以保證信息傳輸的安全。但因爲HTTPS協議新增了SSL/TLS層,在傳輸數據前除了需要完成TCP的三次握手,還需要完成SSL/TLS的握手過程。爲了與HTTP協議相區分,HTTPS協議端口號改爲了443(HTTP協議端口號爲80)。

隨着網絡數據和帶寬的快速增長,HTTP/1.1也遇到了性能瓶頸,以Google爲首的Web服務商不斷改進優化HTTP協議,比如Google於2012年發佈的SPDY(speedy)以會話層的形式加入,可以爲請求報文賦予優先級解決對頭阻塞問題,可以壓縮HTTP首部提高通信效率,支持服務器主動向客戶端推送數據的功能等,SPDY後來成爲HTTP/2標準開發的起點。2015年,HTTP/2標準規範發佈於RFC7540,HTTP/2相比HTTP/1.1主要的性能改進如下( HTTP/2 的規範並不明確要求 TLS,也支持以明文通信,但主流瀏覽器都不支持基於非 TLS 的 HTTP/2,因此 TLS 層也就在事實上相當於是強制性的,HTTP/2 也成爲一次推動全網加密通信發展的機會):

  • 頭部壓縮HPACK:在客戶端和服務器同時維護一張頭信息表,所有字段都會存入這個表,生成一個索引號,以後就不發送同樣字段了,只發送索引號,這樣就提高速度了;
  • 二進制格式傳輸:HTTP/2 不再像 HTTP/1.1 裏的純文本形式的報文,而是全面採用了二進制格式,這樣雖然對人不友好,但計算機可以直接解析二進制報文,提高了數據處理速度;
  • 數據流管理:HTTP/2 的數據包不是按順序發送的,同一個連接裏面連續的數據包可能屬於不同的迴應,每個請求或迴應的所有數據包稱爲一個數據流(Stream),每個數據流都標記着一個獨一無二的編號,客戶端可以指定數據流的優先級;
  • 多路複用:HTTP/2 可以在一個連接中併發多個請求或迴應,而不用按照順序一一對應(HTTP/1.1需要按照順序響應),解決了隊頭阻塞的問題,降低了延遲,大幅度提高了連接的利用率;
  • 服務器推送:HTTP/2 在一定程度上改善了傳統的「請求 - 應答」工作模式,服務不再是被動地響應,也可以主動向客戶端發送消息。

HTTP/2協議分層模型

HTTP/2 協議 主要的問題在於:多個 HTTP 請求在複用一個 TCP 連接,下層的 TCP 協議是不知道有多少個 HTTP 請求的。所以一旦發生了丟包現象,就會觸發 TCP 的重傳機制,這樣在一個 TCP 連接中的所有的 HTTP 請求都必須等待這個丟了的包被重傳回來。這是基於 TCP 傳輸層的問題,所以 HTTP/3 把 HTTP 下層的 TCP 協議改成了 UDP。UDP協議不管理數據包,因此不會出現TCP丟包重傳的問題,但UDP是不可靠的傳輸,Google基於UDP開發了QUIC協議有自己的一套機制可以保證傳輸的可靠性的,當某個流發生丟包時,只會阻塞這個流,其他流不會受到影響。2016年,IETF(Internet Engineering Task Force)成立了QUIC工作組,並在2018年將 QUIC 上的 HTTP 映射稱爲 “HTTP/3”,直到2020年HTTP/3仍處於草案更新階段,距離正式標準發佈估計還有一段不短的路要走。
HTTP/3協議分層模型
HTTP/3 協議使用UDP+QUIC代替TCP協議管理數據流的可靠傳輸,同時將報文頭部壓縮算法升級爲QPACK、加密層協議升級爲TLS 1.3版本。由於QUIC 協議相當於 TCP + TLS 1.3 合併,TCP 握手包可以攜帶TLS 握手包數據,相比HTTPS 建立連接時的六次握手過程(TCP 三次握手 + TLS 1.3 三次握手),QUIC只需要三次握手過程(每個建立連接的握手包攜帶一個TLS 協商密鑰的握手包)即可,減少了交互次數。
HTTP/3協議握手過程

更多文章:

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