http的發(fā)展史

在學習網(wǎng)絡(luò)之前,了解它的歷史能夠幫助我明白為何它會發(fā)展為如今這個樣子,能讓我有探究它的興趣。下面的這張圖片就展示了“互聯(lián)網(wǎng)”誕生至今的發(fā)展歷程

http是什么?

HyperTextTra" />

国产成人精品无码青草_亚洲国产美女精品久久久久∴_欧美人与鲁交大毛片免费_国产果冻豆传媒麻婆精东

18143453325 在線咨詢 在線咨詢
18143453325 在線咨詢
所在位置: 首頁 > 營銷資訊 > 建站知識 > 一文帶你深入了解HTTP

一文帶你深入了解HTTP

時間:2023-02-22 06:51:01 | 來源:建站知識

時間:2023-02-22 06:51:01 來源:建站知識

一文帶你深入了解HTTP:

http的發(fā)展史

在學習網(wǎng)絡(luò)之前,了解它的歷史能夠幫助我明白為何它會發(fā)展為如今這個樣子,能讓我有探究它的興趣。下面的這張圖片就展示了“互聯(lián)網(wǎng)”誕生至今的發(fā)展歷程

http是什么?

HyperTextTransferProtocol 直譯為“超文本傳輸協(xié)議”。

1.超文本:指文字、圖片、視頻、音頻等的混合體,比如最熟悉的html。

2.傳輸:http是一個“雙向協(xié)議”,傳輸?shù)氖钦埱蠓胶晚憫街g的數(shù)據(jù),不限制請求方和響應方之間的角色,傳遞的過程中可以存在任意“中間人”。

3.協(xié)議:協(xié)是兩個或多個參與者之間的交流,議是指對參與者之間的約定和規(guī)范。所以,http協(xié)議可以理解為作用在計算機之間,使用計算機能夠理解的語言確立計算機之間交流通信的規(guī)范,以及相關(guān)的各種控制和錯誤處理方式。

所以對于以上的問題可以有這樣的總結(jié):http是一個在計算機世界里專門在兩點之間傳遞文字、圖片、音頻、視頻等超文本數(shù)據(jù)的約定和規(guī)范。

與http相關(guān)的一些概念

瀏覽器(web Browser):瀏覽器的本質(zhì)是http中的請求方,使用http協(xié)議獲得網(wǎng)絡(luò)上的各種資源。在HTTP協(xié)議里,瀏覽器的角色被稱為"User Agent"即用戶代理,意思是作為訪問者的”代理來發(fā)起HTTP請求。下圖是一些主流瀏覽器及其內(nèi)核。

服務器(web Server):硬件含義就是物理形式或“云”形式的機器。軟件含義的 Web 服務器就是提供 Web 服務的應用程序,通常會運行在硬件含義的服務器上。它利用強大的硬件能力響應海量的客戶端 HTTP 請求,返回動態(tài)的信息。常見的web服務器有Apache、Nginx。

CDN(Content Delivery Network):CDN是為了解決長距離網(wǎng)絡(luò)訪問速度慢的問題而誕生的一種網(wǎng)絡(luò)應用服務,全稱為“內(nèi)容分發(fā)網(wǎng)絡(luò)”。CDN最核心的原則是“就近訪問”,使用HTTP協(xié)議里的代理和緩存技術(shù),用戶在上網(wǎng)的時候不直接訪問原網(wǎng)站,而是訪問離他最近的一個CDN節(jié)點,節(jié)省了訪問過程中的時間成本。(負載均衡,安全防護,邊緣計算)。

爬蟲(Crawler):“機器人”形式的用戶代理,是一種可以自動訪問Web資源的應用程序。

HTML(Hyper Text Markup Language):超文本標記語言,用于描述超文本頁面,用標簽定義圖片、文字、排版布局,最終由瀏覽器渲染。

web Service:由W3C定義的應用服務開發(fā)規(guī)范,使用client-server主從架構(gòu)。是一個基于Web(HTTP)的服務架構(gòu)技術(shù)。

WAF:網(wǎng)絡(luò)應用防火墻,位于Web服務器之前,專門檢測http流量,是防護web應用安全的技術(shù)??梢宰柚筍QL注入,跨站腳本攻擊,可以完全集成進Apache或Nginx。

TCP/IP:一系列網(wǎng)絡(luò)通信協(xié)議的統(tǒng)稱,其中最核心的是TCP和IP協(xié)議。其他的還有UDP,ICMP,ARP等,共同構(gòu)成一個復雜但有層次的協(xié)議棧。IP(Internet Protocol)協(xié)議主要解決尋址和路由問題,以及如何在兩點之間傳輸數(shù)據(jù)包。TCP(Transmission Control Protoco)協(xié)議位于IP協(xié)議之上,意思是“傳輸控制協(xié)議”,基于IP協(xié)議提供可靠的、字節(jié)流形式的通信,是HTTP協(xié)議實現(xiàn)的基礎(chǔ)?;ヂ?lián)網(wǎng)上的 HTTP 協(xié)議運行在 TCP/IP 上,HTTP 也就可以更準確地稱為“HTTP over TCP/IP”。

DNS(Domain Name System): 域名系統(tǒng),用有意義的名字來作為 IP 地址的等價替代。在 DNS 中,“域名”(Domain Name)又稱為“主機名”(Host)。域名用“.”分隔成多個單詞,級別從左到右逐級升高,最右邊的被稱為“頂級域名”。但想要使用 TCP/IP 協(xié)議來通信仍然要使用 IP 地址,所以需要把域名做一個轉(zhuǎn)換,“映射”到它的真實 IP,這就是所謂的“域名解析”。

URI/URL:URI(Uniform Resource Identifier)中文名稱是統(tǒng)一資源標識符。DNS 和 IP 地址只是標記了互聯(lián)網(wǎng)上的主機,URI能夠唯一地標記互聯(lián)網(wǎng)上資源。URI 另一個更常用的表現(xiàn)形式是 URL(Uniform Resource Locator), 統(tǒng)一資源定位符,也就是我們俗稱的“網(wǎng)址”,它實際上是 URI 的一個子集,通常不會做嚴格的區(qū)分。

URI 主要有三個基本的部分構(gòu)成:
1.協(xié)議名:即訪問該資源應當使用的協(xié)議

2.主機名:即互聯(lián)網(wǎng)上主機的標記,可以是域名或 IP 地址

3.路徑:即資源在主機上的位置,使用“/”分隔多級目錄

HTTPS:全稱是“HTTP over SSL/TLS”,也就是運行在 SSL/TLS 協(xié)議上的 HTTP。它是一個負責加密通信的安全協(xié)議,建立在 TCP/IP 之上,所以也是個可靠的傳輸協(xié)議,可以被用作 HTTP 的下層,相當于“HTTP+SSL/TLS+TCP/IP”。

代理(Proxy): 是 HTTP 協(xié)議中請求方和應答方中間的一個環(huán)節(jié),作為“中轉(zhuǎn)站”,既可以轉(zhuǎn)發(fā)客戶端的請求,也可以轉(zhuǎn)發(fā)服務器的應答。

代理有很多的種類,常見的有:
1.匿名代理:完全“隱匿”了被代理的機器,外界看到的只是代理服務器;

2.透明代理:顧名思義,它在傳輸過程中是“透明開放”的,外界既知道代理,也知道客戶端;

3.正向代理:靠近客戶端,代表客戶端向服務器發(fā)送請求;

4.反向代理:靠近服務器端,代表服務器響應客戶端的請求;

網(wǎng)絡(luò)的分層模型

網(wǎng)絡(luò)分層模型層級是從下往上數(shù)的,一般我們比較常接觸到的是TCP/IP四層模型,也是比較早出現(xiàn)的分層模型。

第一層是鏈路層(link layer),負責在底層網(wǎng)絡(luò)上發(fā)送原始數(shù)據(jù)包,工作在網(wǎng)卡這個層次,使用 MAC 地址來標記網(wǎng)絡(luò)上的設(shè)備,所以有時候也叫 MAC 層。對應的是ISO模型的"數(shù)據(jù)鏈路層"。

第二層叫網(wǎng)絡(luò)層(internet layer),IP協(xié)議就處在這一層。因為IP協(xié)議定義了"IP 地址"的概念,所以就可以在"鏈路層"的基礎(chǔ)上,用IP地址取代MAC地址,在這個網(wǎng)絡(luò)里找設(shè)備時只要把IP 地址再翻譯成MAC地址就可以了。對應的是ISO模型的"網(wǎng)絡(luò)層"。

第三層叫"傳輸層"(transport layer),這個層次協(xié)議的職責是保證數(shù)據(jù)在IP地址標記的兩點之間可靠地傳輸,是TCP協(xié)議和UDP協(xié)議工作的層次。對應的是ISO模型的"傳輸層"。

第四層叫"應用層"(application layer),由于下面的三層把基礎(chǔ)打得非常好,所以在這一層就"百花齊放"了,有各種面向具體應用的協(xié)議。例如 Telnet、SSH、FTP、SMTP 等等,當然還有我們的 HTTP。 對應的是ISO模型的"會話層","表示層","應用層"。

利用TCP/IP協(xié)議族進行網(wǎng)絡(luò)通信時,會通過分層順序與對方進行通信(發(fā)送端從應用層往下走,接收端從應用層往上走)。

域名

域名是一個有層次的結(jié)構(gòu),是一串用“.”分隔的多個單詞,最右邊的被稱為“頂級域名”,然后是“二級域名”,層級關(guān)系向左依次降低。最左邊的是主機名,通常用來表明主機的用途,比如“www”表示提供萬維網(wǎng)服務、“mail”表示提供郵件服務,不過這也不是絕對的。
可以通過下面的例子了解一下協(xié)議 主機 域名之間的層次關(guān)系。域名就像人的名字一樣,名字的關(guān)鍵是要讓我們?nèi)菀子洃?。除了標識身份之外,域名還可以代替ip地址。

DNS

我們經(jīng)常會使用域名訪問網(wǎng)站,但其實在網(wǎng)絡(luò)查找的工程當中是使用ip定位資源的,域名必須解析為ip地址才可以正確的拿到資源。DNS就是用來將域名變?yōu)閕p的協(xié)議。

DNS 的核心系統(tǒng)是一個三層的樹狀、分布式服務,基本對應域名的結(jié)構(gòu):

1.根域名服務器(Root DNS Server):管理頂級域名服務器,返回"com","net","cn"等頂級域名服務器的 IP 地址。

2.頂級域名服務器(Top-level DNS Server):管理各自域名下的權(quán)威域名服務器,比如 cn 頂級域名服務器可以返回 http://123.cn域名服務器的 IP 地址。

3.權(quán)威域名服務器(Authoritative DNS Server):管理自己域名下主機的 IP 地址,比如 http://123.cn 權(quán)威域名服務器可以返回 http://www.123.cn 的 IP 地址。

雖然DNS的服務,遍布全球,服務能力也很厲害,但是全世界的網(wǎng)民都在使用這個服務,也會對服務器造成很大的壓力。在核心 DNS 系統(tǒng)之外,還有兩種手段用來減輕域名解析的壓力,并且能夠更快地獲取結(jié)果,基本思路就是“緩存”。

DNS的解析結(jié)果可以保存在大公司自己的DNS服務器里,或者操作系統(tǒng)緩存、hosts 文件當中,很多域名解析的工作就都不用請求根DNS服務器了,直接在本地或本機就能解決,不僅方便了用戶,也減輕了各級 DNS 服務器的壓力,效率就大大提升了。

基于域名和DNS服務器,我們可以實現(xiàn)重定向。因為域名代替了ip地址,所以可以對外域名不變,而主機IP可以任意變動。當主機有情況需要下線、遷移時,可以更改 DNS 記錄,讓域名指向其他的機器。

我們應該都聽說過負載均衡吧,DNS在域名解析階段就可以進行負載均衡的操作。

第一種方式,因為域名解析可以返回多個 IP 地址,所以一個域名可以對應多臺主機,客戶端收到多個 IP 地址后,就可以自己使用輪詢算法依次向服務器發(fā)起請求,實現(xiàn)負載均衡。

第二種方式,域名解析可以配置內(nèi)部的策略,返回離客戶端最近的主機,或者返回當前服務質(zhì)量最好的主機,這樣在 DNS 端把請求分發(fā)到不同的服務器,實現(xiàn)負載均衡。

HTTP/1.X



前面我們說了HTTP就是“超文本傳輸協(xié)議”,是一個在計算機世界里專門在兩點之間傳遞文字、圖片、音頻、視頻等超文本數(shù)據(jù)的約定和規(guī)范。在學習過網(wǎng)絡(luò)的層次模型之后我們又了解了HTTP是一個應用層的協(xié)議。在這個環(huán)節(jié)我們開始正式深入HTTP的世界(基于http/1.1)。

(一)HTTP報文

HTTP 協(xié)議的請求報文和響應報文的結(jié)構(gòu)基本相同,由三大部分組成:

1.起始行(start line):描述請求或響應的基本信息;

2.頭部字段集合(header):使用 key-value 形式更詳細地說明報文;

3.消息正文(entity):實際傳輸?shù)臄?shù)據(jù),它不一定是純文本,可以是圖片、視頻等二進制數(shù)據(jù)。

請求行一般用來描述客戶端要怎樣操作服務端的資源,一般由三個部分組成。通常使用空格(space)來分隔,最后要用 CRLF 換行表示結(jié)束。

狀態(tài)行一般用來描述服務端對于客戶端的請求回復的狀態(tài),一般也是由三個部分組成。

請求行或狀態(tài)行再加上頭部字段集合就構(gòu)成了 HTTP 報文里完整的請求頭或響應頭。除了起始行以外,請求頭和響應頭的結(jié)構(gòu)基本相同。HTTP 頭字段非常靈活,不僅可以使用標準里的 Host、Connection 等已有頭,也可以任意添加自定義頭。不過使用頭字段需要注意下面幾點:

1.字段名不區(qū)分大小寫,例如“Host”也可以寫成“host”,但首字母大寫的可讀性更好。

2.字段名里不允許出現(xiàn)空格,可以使用連字符“-”,但不能使用下劃線“_”。例如,“test-name”是合法的字段名,而“test name”“test_name”是不正確的字段名。

3.字段名后面必須緊接著“:”,不能有空格,而“:”后的字段值前可以有多個空格。

4.字段的順序是沒有意義的,可以任意排列不影響語義。

5.字段原則上不能重復,除非這個字段本身的語義允許,例如 Set-Cookie。

(二)HTTP請求方法



目前 HTTP/1.1 規(guī)定了八種方法,單詞都必須是大寫的形式,下面就來看看這些方法:

1.GET:獲取資源,可以理解為讀取或者下載數(shù)據(jù)。

2.HEAD:獲取資源的元信息。

3.POST:向資源提交數(shù)據(jù),相當于寫入或上傳數(shù)據(jù)。

4.PUT:類似 POST。

5.DELETE:刪除資源。

6.CONNECT:建立特殊的連接隧道。

7.OPTIONS:列出可對資源實行的方法。

8.TRACE:追蹤請求 - 響應的傳輸路徑。

這幾個是我們比較常用的方法,有必要好好學習一下。

GET和HEAD

  1. GET適用于向服務器請求資源,一般將數(shù)據(jù)攜帶于url上。
  2. HEAD類似于簡化版的GET請求,服務端收到HEAD請求時只返回響應頭并且響應頭與GET完全一致。
POST和PUT

  1. POST 適用于向服務端發(fā)送數(shù)據(jù),將數(shù)據(jù)攜帶在body當中,通常表示的是“create”的含義。
  2. PUT 類似于POST方法,也可以向服務器提交數(shù)據(jù),是“update”的含義。
GET和POST的區(qū)別

在這里特別容易被問到的問題是GET和POST的區(qū)別,我也想在這塊詳細的寫一下。以下是基于我個人的理解
1. 大小:GET通常將數(shù)據(jù)帶在URL當中而POST將數(shù)據(jù)放在body里(是RFC在語義上的要求,語法上GET也可以使用body傳輸數(shù)據(jù)而POST同樣可以把參數(shù)放在URL里),因此由于瀏覽器對于URL長度的限制,GET請求能攜帶的數(shù)據(jù)大小一般不超過2KB。值得一提Chrome瀏覽器對URL的長度限制已經(jīng)增加到2MB,但是我們考慮到兼容性,URL的長度應該以最大限制的最小標準為主(IE瀏覽器限制為2KB),除了瀏覽器的限制,還應該考慮到服務端的限制。

2. 安全:安全是指請求的方法是否會對服務器當中的資源造成影響,因為GET方法是只讀的,只要服務器沒有“曲解”客戶端的請求,服務端上的數(shù)據(jù)就是安全的。而POST會對服務端的數(shù)據(jù)進行“增刪改”的操作,因此是不安全的。

3. 冪等:冪等的意思是說多次重復執(zhí)行操作,產(chǎn)生的效果是否相同。顯然因為GET方法只對服務器上的資源做只讀操作,因此是冪等的。POST在RFC中的定義是“新增或提交數(shù)據(jù)”,多次提交數(shù)據(jù)會創(chuàng)建多個資源,所以不是冪等的(而 PUT 是“替換或更新數(shù)據(jù)”,多次更新一個資源,所以是冪等的)。

4. 緩存: 就是說這個方法的可緩存性,絕大多數(shù)的瀏覽器的實現(xiàn)里僅僅支持GET緩存。因為GET因為是讀取,就可以對GET請求的數(shù)據(jù)做緩存。而POST不冪等也就意味著不能隨意多次執(zhí)行。因此也就不能緩存。

(三)URI是什么

URI,也就是統(tǒng)一資源標識符(Uniform Resource Identifier)。因為它經(jīng)常出現(xiàn)在瀏覽器的地址欄里,所以俗稱為“網(wǎng)絡(luò)地址”,簡稱“網(wǎng)址”。URI 不完全等同于網(wǎng)址,它包含有 URL 和 URN 兩個部分,在 HTTP 世界里用的網(wǎng)址實際上是 URL——統(tǒng)一資源定位符(Uniform Resource Locator)。但因為 URL 實在是太普及了,所以常常把這兩者簡單地視為相等。



URI 本質(zhì)上是一個字符串,這個字符串的作用是唯一地標記資源的位置或者名字。

上面這個圖片就是一個完整的URI,下面詳細拆解一下它的結(jié)構(gòu)。

scheme 協(xié)議名,表示資源應該使用哪種協(xié)議來訪問。最常見的當然就是“http”了,表示使用 HTTP 協(xié)議。另外還有“https”,表示使用經(jīng)過加密、安全的 HTTPS 協(xié)議。此外還有其他不是很常見的 scheme,例如 ftp、ldap、file、news 等。

:// 分隔符,在 scheme 之后,必須是三個特定的字符“://”,它把 scheme 和后面的部分分離開。沒有特定的意義。

user:passwd@ 身份信息,表示登錄主機時的用戶名和密碼,但現(xiàn)在已經(jīng)不推薦使用這種形式了,因為它把敏感信息以明文形式暴露出來,存在嚴重的安全隱患。

host:port主機名,表示資源所在的主機名,通常的形式是“host:port”,即主機名加端口號。

path 路徑,表示資源所在位置,采用了類似文件系統(tǒng)“目錄”的表示方式,通常以‘/’開始

query 查詢參數(shù),用一個“?”開始,但不包含“?”,表示對資源附加的額外要求。path是多個“key=value”的字符串,這些字符串用字符“&”連接,瀏覽器和服務器都可以按照這個格式把長串的查詢參數(shù)解析成可理解的字典或關(guān)聯(lián)數(shù)組形式。

#fragment 片段標識符,它是 URI 所定位的資源內(nèi)部的一個“錨點”,瀏覽器可以在獲取資源后直接跳轉(zhuǎn)到它指示的位置。但片段標識符僅能由瀏覽器這樣的客戶端使用,服務器是看不到的。

在 URI 里只能使用 ASCII 碼,對于 ASCII 碼以外的字符集和特殊字符做一個特殊的操作,把它們轉(zhuǎn)換成與 URI 語義不沖突的形式。這在 RFC 規(guī)范里稱為“escape”和“unescape”,俗稱“轉(zhuǎn)義”。URI 轉(zhuǎn)義的規(guī)則有點“簡單粗暴”,直接把非 ASCII 碼或特殊字符轉(zhuǎn)換成十六進制字節(jié)值,然后前面再加上一個“%”。

(四)狀態(tài)碼

在HTTP報文部分我們說了HTTP的狀態(tài)行,我們在這個部分就來看看狀態(tài)行中的狀態(tài)碼。

狀態(tài)碼是一個十進制的數(shù)字,RFC 標準把狀態(tài)碼分成了五類,用數(shù)字的第一位表示分類,而 0 ~ 99 不用,這樣狀態(tài)碼的實際可用范圍就變成了 100~599。這五類的具體含義是:





1××

1×× 類狀態(tài)碼屬于提示信息,是協(xié)議處理的中間狀態(tài),實際能夠用到的時候很少。

"100 Continue"應該是比較常接觸到的,會在POST請求發(fā)送大文件給服務器時詢問服務器是否能夠接受時使用,需要帶上請求頭Expect: 100-continue。這個過程也就是我們常說的POST發(fā)送兩個TCP包給服務器的說法的來源,不過客戶端不需要一直等待服務端的回應,在一定時間內(nèi)沒有收到否定的回答還是會將數(shù)據(jù)主體發(fā)送給服務器。

2××

2×× 類狀態(tài)碼表示服務器收到并成功處理了客戶端的請求,這也是客戶端最愿意看到的狀態(tài)碼。

“200 OK”是最常見的成功狀態(tài)碼,表示一切正常,服務器如客戶端所期望的那樣返回了處理結(jié)果,如果是非 HEAD 請求,通常在響應頭后都會有 body 數(shù)據(jù)。

“204 No Content”是另一個很常見的成功狀態(tài)碼,它的含義與“200 OK”基本相同,但響應頭后沒有 body 數(shù)據(jù)。所以對于 Web 服務器來說,正確地區(qū)分 200 和 204 是很必要的。

“206 Partial Content”是 HTTP 分塊下載或斷點續(xù)傳的基礎(chǔ),在客戶端發(fā)送“范圍請求”、要求獲取資源的部分數(shù)據(jù)時出現(xiàn),它與 200 一樣,也是服務器成功處理了請求,但 body 里的數(shù)據(jù)不是資源的全部,而是其中的一部分。狀態(tài)碼 206 通常還會伴隨著頭字段Content-Range,表示響應報文里 body 數(shù)據(jù)的具體范圍,供客戶端確認,例如“Content-Range: bytes 0-99/2000”,意思是此次獲取的是總計 2000 個字節(jié)的前 100 個字節(jié)。

3××

3××類狀態(tài)碼表示客戶端請求的資源發(fā)生了變動,客戶端必須用新的 URI 重新發(fā)送請求獲取資源,也就是通常所說的“重定向”,包括著名的 301、302 跳轉(zhuǎn)。

“301 Moved Permanently” 俗稱“永久重定向”,含義是此次請求的資源已經(jīng)不存在了,需要改用改用新的 URI 再次訪問。

“302 Found”,曾經(jīng)的描述短語是“Moved Temporarily”,俗稱“臨時重定向”,意思是請求的資源還在,但需要暫時用另一個 URI 來訪問。

“304 Not Modified” 是一個比較有意思的狀態(tài)碼,它用于 If-Modified-Since 等條件請求,表示資源未修改,用于緩存控制。它不具有通常的跳轉(zhuǎn)含義,但可以理解成“重定向已到緩存的文件”(即“緩存重定向”)。

4××

4××類狀態(tài)碼表示客戶端發(fā)送的請求報文有誤,服務器無法處理,它就是真正的“錯誤碼”含義了。

“400 Bad Request” 是一個通用的錯誤碼,表示請求報文有錯誤,只是一個籠統(tǒng)的錯誤,沒有明確含義的狀態(tài)碼。

“403 Forbidden” 實際上不是客戶端的請求出錯,而是表示服務器禁止訪問資源。

“404 Not Found” 原意是資源在本服務器上未找到,所以無法提供給客戶端。但現(xiàn)在已經(jīng)被“用濫了”,只要服務器“不高興”就可以給出個 404,而我們也無從得知后面到底是真的未找到,還是有什么別的原因,某種程度上它比 403 還要令人討厭。

5××

5××類狀態(tài)碼表示客戶端請求報文正確,但服務器在處理時內(nèi)部發(fā)生了錯誤,無法返回應有的響應數(shù)據(jù),是服務器端的“錯誤碼”。

“500 Internal Server Error” 與 400 類似,也是一個通用的錯誤碼,服務器究竟發(fā)生了什么錯誤我們是不知道的。不過對于服務器來說這應該算是好事,通常不應該把服務器內(nèi)部的詳細信息,例如出錯的函數(shù)調(diào)用棧告訴外界。雖然不利于調(diào)試,但能夠防止黑客的窺探或者分析。

“501 Not Implemented” 表示客戶端請求的功能還不支持,這個錯誤碼比 500 要“溫和”一些,和“即將開業(yè),敬請期待”的意思差不多,不過具體什么時候“開業(yè)”就不好說了。

“502 Bad Gateway” 通常是服務器作為網(wǎng)關(guān)或者代理時返回的錯誤碼,表示服務器自身工作正常,訪問后端服務器時發(fā)生了錯誤,但具體的錯誤原因也是不知道的。

“503 Service Unavailable” 表示服務器當前很忙,暫時無法響應服務,我們上網(wǎng)時有時候遇到的“網(wǎng)絡(luò)服務正忙,請稍后重試”的提示信息就是狀態(tài)碼 503。503 是一個“臨時”的狀態(tài),很可能過幾秒鐘后服務器就不那么忙了,可以繼續(xù)提供服務,所以 503 響應報文里通常還會有一個“Retry-After”字段,指示客戶端可以在多久以后再次嘗試發(fā)送請求。

(五)HTTP的特點



1.靈活可擴展:HTTP在誕生之初只規(guī)定了報文的基本格式,比如用空格分隔單詞,用換行分隔字段,“header+body”等,報文里的各個組成部分都沒有做嚴格的語法語義限制,可以由開發(fā)者任意定制。而那些 RFC 文檔,實際上也可以理解為是對已有擴展的“承認和標準化”,實現(xiàn)了“從實踐中來,到實踐中去”的良性循環(huán)。

2.可靠傳輸: 因為 HTTP 協(xié)議是基于 TCP/IP 的,而 TCP 本身是一個“可靠”的傳輸協(xié)議,所以 HTTP 自然也就繼承了這個特性,能夠在請求方和應答方之間“可靠”地傳輸數(shù)據(jù)。

3.應用層的協(xié)議: HTTP 憑借著可攜帶任意頭字段和實體數(shù)據(jù)的報文結(jié)構(gòu),以及連接控制、緩存代理等方便易用的特性,只要不太苛求性能,HTTP 幾乎可以傳遞一切東西,滿足各種需求,稱得上是一個“萬能”的協(xié)議。

4.請求 - 應答:請求 - 應答模式是 HTTP 協(xié)議最根本的通信模型,通俗來講就是“一發(fā)一收”。請求 - 應答模式也明確了 HTTP 協(xié)議里通信雙方的定位,永遠是請求方先發(fā)起連接和請求,是主動的,而應答方只有在收到請求后才能答復,是被動的,如果沒有請求時不會有任何動作。

5.無狀態(tài): “狀態(tài)”其實就是客戶端或者服務器里保存的一些數(shù)據(jù)或者標志,記錄了通信過程中的一些變化信息。HTTP在整個協(xié)議里沒有規(guī)定任何的“狀態(tài)”,但不要忘了 HTTP 是“靈活可擴展”的,雖然標準里沒有規(guī)定“狀態(tài)”,但完全能夠在協(xié)議的框架里給它“打個補丁”,增加這個特性(cookie)。

6.明文傳輸: “明文”意思就是協(xié)議里的報文(準確地說是 header 部分)不使用二進制數(shù)據(jù),而是用簡單可閱讀的文本形式。

7.不安全: 安全有很多的方面,明文只是“機密”方面的一個缺點,在“身份認證”和“完整性校驗”這兩方面 HTTP 也是欠缺的。

(六)HTTP的實體數(shù)據(jù)

Accept在TCP/IP協(xié)議棧里,數(shù)據(jù)的傳輸都是Header+body的形式。在傳輸層協(xié)議中,不需要關(guān)心數(shù)據(jù)是什么,但在應用層必須要告訴上層數(shù)據(jù)的類型,否則上層就不知該如何處理。最早的HTTP協(xié)議中,并沒有附加的數(shù)據(jù)類型信息,所有傳送的數(shù)據(jù)都被客戶程序解釋為HTML文檔,而為了支持多媒體數(shù)據(jù)類型,HTTP協(xié)議中就使用了附加在文檔之前的MIME(Multipurpose Internet Mail Extensions 多用途互聯(lián)網(wǎng)郵件擴展類型)指定的數(shù)據(jù)類型信息來標識數(shù)據(jù)類型。MINE將數(shù)據(jù)分為七大類(video、image、application、text、audio、multipart、message),再以type/subtype的格式細分出其下的子類。例如我們常用到的text/html 、text/css 、image/jpeg 、 applaction/json等。Accept-encoding

此外HTTP協(xié)議還制定了數(shù)據(jù)的壓縮格式:

gzip:GNU zip 壓縮格式,也是互聯(lián)網(wǎng)上最流行的壓縮格式;

deflate:zlib(deflate)壓縮格式,流行程度僅次于 gzip;

br:一種專門為 HTTP 優(yōu)化的新壓縮算法(Brotli)。

Accept-Language

標記了客戶端可理解的自然語言,也允許用“,”做分隔符列出多個類型,例如:Accept-Language: zh-CN, zh, en

在 HTTP 協(xié)議里用 Accept、Accept-Encoding、Accept-Language 等請求頭字段進行內(nèi)容協(xié)商的時候,還可以用一種特殊的“q”參數(shù)表示權(quán)重來設(shè)定優(yōu)先級,這里的“q”是“quality factor”的意思。權(quán)重的最大值是 1,最小值是 0.01,默認值是 1,如果值是 0 就表示拒絕。具體的形式是在數(shù)據(jù)類型或語言代碼后面加一個“;”,然后是“q=value”。服務器會在響應頭里多加一個 Vary 字段,記錄服務器在內(nèi)容協(xié)商時參考的請求頭字段。

(七)HTTP如何傳輸大文件

1.數(shù)據(jù)壓縮

前面提到的accept-encoding請求頭可以算是是一種傳輸大文件的解決方式,服務器可以選擇一種瀏覽器支持的數(shù)據(jù)壓縮方式放進content-encoding響應頭里,再把原數(shù)據(jù)壓縮后返回給客戶端。缺點是這種方式只對文本有較好地壓縮率,對于圖片音頻等本身就已經(jīng)高度壓縮的多媒體數(shù)據(jù)束手無策。

2.分塊傳輸在HTTP頭部表示為Transfer-Encoding: chunked,指報文里的body部分不是一次性發(fā)過來的,而是分為許多chunked分塊發(fā)送。Transfer-Encoding: chunked和Content-Length這兩個字段是互斥的,也就是說響應報文里這兩個字段不能同時出現(xiàn),一個響應報文的傳輸要么是長度已知,要么是長度未知(chunked),這一點你一定要記住。

3.范圍請求如果想獲取某個大文件其中的片段,分塊傳輸就沒辦法滿足這樣的需求。HTTP協(xié)議提出了范圍請求這樣的概念,允許客戶端只獲取文件的某一部分??蛻舳讼劝l(fā)個HEAD請求看看服務器是否支持范圍請求,服務器必須在Accept-Ranges響應頭中告知客戶端是否具有范圍請求的能力。請求頭Ranges是HTTP范圍請求的專用字段,值的格式是bytes=x-y表示x ~ y之間的范圍。服務端在收到 Ranges請求頭時,首先驗證x-y的范圍是否合法(x和y可以省略,省略x則表示從后往前,省略y則表示從前往后),其次計算讀取偏移量,返回206狀態(tài)碼和所讀取的文件 ,最后在響應頭加上Content-Range表示實際返回的偏移量和總數(shù),格式為bytes x-y/length。

范圍請求還支持在一個頭里定義多個x-y,這種情況需要一種特殊的MIME類型multipart/byteranges,表示報文是有多段組成。

(八)HTTP連接管理

http的通信過程采取請求/應答模式,在http0.9/1.0時期,每次發(fā)起請求都需要建立連接->發(fā)送數(shù)據(jù)->斷開連接,由于整個請求的過程非常短暫,早起的http也稱為短鏈接無鏈接的協(xié)議。由于TCP簡歷連接要經(jīng)過三次握手四次揮手,整個過程需要3個RTT,而HTTP的一次簡單請求通常只需要2個RTT,那么被浪費掉的時間有60%。

HTTP1.1提出了長連接的概念,也就是Keep-alive。在長連接上建立一次TCP連接可以發(fā)送多個HTTP請求。但因為連接是alive的,如果一直不關(guān)閉,就會占用大量的服務器資源,導致服務無法及時響應真正的請求,所以我們也需要及時關(guān)閉連接??梢酝ㄟ^在客戶端請求頭添加Connection: close字段主動關(guān)閉連接。服務端通常不會主動關(guān)閉連接,但我們也可以通過設(shè)置時長、請求數(shù)等方式約定斷開連接的條件。

基于請求-應答模式的http協(xié)議,形成了串行的請求隊列(http1.1還提出了管道機制,即在同一個TCP連接上不用等待上一個請求的響應即可發(fā)出下個請求,不過客戶端還是按照正常順序接受響應,這種做法并沒帶來任何性能上的改善,所以默認保持關(guān)閉),如果隊首的請求處于阻塞狀態(tài),那么后面的請求也無法正常響應結(jié)果就是更長時間的性能浪費。

并發(fā)連接和域名分片是對隊頭阻塞的針對性優(yōu)化策略,瀏覽器限制每個客戶端可以并發(fā)建立6~8個連接,又可以將多個域名指向同一個服務器,這樣實際的連接數(shù)量就更多了,是一種用數(shù)量解決質(zhì)量的思路。

當我們在瀏覽器輸入一個url再按下回車,頁面跳轉(zhuǎn)到我們輸入的地址中,這種行為就是主動跳轉(zhuǎn)。瀏覽器還支持被動跳轉(zhuǎn),也就是HTTP的重定向。

狀態(tài)碼

在前面了解過HTTP狀態(tài)碼,3XX即表示為重定向。下面詳細介紹下各個狀態(tài)碼的含義。

301指永久重定向,可能是域名下線,域名遷移等原因,原地址不再維護。此時瀏覽器在重定向的同時記錄重定向后的地址,下次訪問該域名就自動訪問新的URI了。

302指臨時重定向,可能是服務器維護、臨時關(guān)閉等原因,臨時跳轉(zhuǎn)到新的地址上,此時瀏覽器不會記錄重定向的地址,認為原地址還是有效的,下次訪問時還是優(yōu)先訪問原地址。

303類似 302,但要求重定向后的請求改為 GET 方法,訪問一個結(jié)果頁面,避免 POST/PUT 重復操作。

307類似 302,但重定向后請求里的方法和實體不允許變動,含義比 302 更明確。

308類似 307,不允許重定向后的請求變動,但它是 301“永久重定向”的含義。

可以在地址欄輸入bing.com,瀏覽器控制臺中的狀態(tài)如下圖所示:

客戶端是如何處理重定向的在瀏覽器地址欄輸入bing.con我們可以看到,狀態(tài)碼如下圖所示:我們?yōu)g覽器收到響應之后根據(jù)響應頭中的Location字段判斷重定向的地址,然后進行被動跳轉(zhuǎn)。雖然重定向的用途很廣,但是隨之而來的也有更多問題。

第一個問題是“性能損耗”。很明顯,重定向的機制決定了一個跳轉(zhuǎn)會有兩次請求 - 應答,比正常的訪問多了一次。雖然 301/302 報文很小,但大量的跳轉(zhuǎn)對服務器的影響也是不可忽視的。站內(nèi)重定向可以長連接復用,站外重定向就要開兩個連接。

第二的問題是循環(huán)重定向,比如 A->B->C->A,當我們訪問A時就會發(fā)生無限跳轉(zhuǎn)。所以HTTP協(xié)議特別規(guī)定,瀏覽器必須具有檢測“循環(huán)跳轉(zhuǎn)”的能力,在發(fā)現(xiàn)這種情況時應當停止發(fā)送請求并給出錯誤提示。

(九)cookie

HTTP 是“無狀態(tài)”的,這既是優(yōu)點也是缺點。優(yōu)點是服務器沒有狀態(tài)差異,可以很容易地組成集群,而缺點就是無法支持需要記錄狀態(tài)的事務操作。好在 HTTP 協(xié)議是可擴展的,后來發(fā)明的 Cookie 技術(shù),給 HTTP 增加了“記憶能力”。

cookie同樣存在于HTTP頭部字段里。服務端可以使用set-cookie標識客戶端身份,客戶端則在請求時攜帶cookie告訴服務端自己的信息。cookie字段以key=value的格式保存,瀏覽器在一個cookie字段里可以存放多對數(shù)據(jù),用;分割。

Cookie 主要用于以下三個方面:

1.會話狀態(tài)管理(如用戶登錄狀態(tài)、購物車、游戲分數(shù)或其它需要記錄的信息)

2.個性化設(shè)置(如用戶自定義設(shè)置、主題等)

3.瀏覽器行為跟蹤(如跟蹤分析用戶行為等)

生存周期

Expires俗稱“過期時間”,用的是絕對時間點,可以理解為“截止日期”(deadline)。

Max-Age用的是相對時間,單位是秒,瀏覽器用收到報文的時間點再加上 Max-Age,就可以得到失效的絕對時間。

Expires 和 Max-Age 可以同時出現(xiàn),兩者的失效時間不一致時瀏覽器會優(yōu)先采用Max-Age計算失效期。如果服務器不設(shè)置Max-Age、Expries或者字段值為0指不能緩存cookie,但在會話期間是可用的,瀏覽器會話關(guān)閉之前可以用cookie記錄用戶的信息。

作用域

Domain和Path指定了 Cookie 所屬的域名和路徑,瀏覽器在發(fā)送 Cookie 前會從 URI 中提取出 host 和 path 部分,對比 Cookie 的屬性。如果不滿足條件,就不會在請求頭里發(fā)送 Cookie。通常 Path 就用一個“/”或者直接省略,表示域名下的任意路徑都允許使用 Cookie。

安全性

HttpOnly表示此 Cookie 只能通過瀏覽器 HTTP 協(xié)議傳輸,禁止其他方式訪問。這也是預防“跨站腳本”(XSS)攻擊的有效手段。

SameSite可以防范“跨站請求偽造”(XSRF)攻擊,SameSite = strict表示禁止cookie在跳轉(zhuǎn)鏈接時跨域傳輸。SameSite = lax稍微寬松一點,允許在GET、HEAD等安全請求方式中跨域攜帶。默認值為none,表示不限制cookie的攜帶和傳輸。

Secure表示這個cookie僅能用HTTPS協(xié)議加密傳輸,明文的HTTP協(xié)議會禁止發(fā)送。但Cookie本身不是加密的,瀏覽器里還是以明文的形式存在。

(十)HTTP緩存控制

瀏覽器在訪問頁面資源時首先會查找緩存數(shù)據(jù),如果沒有再發(fā)送請求,向服務器獲取資源;服務器響應請求,返回資源,同時標記資源的有效期;瀏覽器緩存資源,等待下次重用。這就是客戶端緩存。服務器標記資源有效期使用的頭字段是Cache-Control,里面的值max-age=xxx就是資源的有效時間(與cookie的max-age不同,這里的max-age時間的計算起點是響應報文的創(chuàng)建時刻)。

此外在響應報文里還可以用其他的值來更精確地指示瀏覽器應該如何使用緩存:
no-store: 不允許緩存,用于某些變化非常頻繁的數(shù)據(jù),例如秒殺頁面。
no-cache: 可以緩存,但在使用之前必須要去服務器驗證是否過期。must-revalidate: 如果緩存不過期就可以繼續(xù)使用,但過期了就必須去服務器驗證。

瀏覽器也可以發(fā)Cache-Control,也就是說請求 - 應答的雙方都可以用這個字段進行緩存控制,互相協(xié)商緩存的使用策略。在瀏覽器前進、后退、重定向時cache-control就生效了,響應頭里有from disk cache字樣,就說明瀏覽器未發(fā)送請求,而是直接使用了本地緩存。

條件請求

瀏覽器在刷新頁面時相當于在請求頭中添加了Cache-Control:no-cache,這樣在刷新頁面時,還是向服務端發(fā)送了請求,并沒有很好的利用到緩存。所以HTTP協(xié)議又定義了一系列“If”開頭的“條件請求”字段,專門用來檢查驗證資源是否過期。

條件請求一共有 5 個頭字段,我們最常用的是if-Modified-Since和If-None-Match這兩個。需要第一次的響應報文預先提供Last-modified(最后修改時間)和ETag(資源唯一標識),然后第二次請求時就可以帶上緩存里的原值,驗證資源是否是最新的。如果資源沒有變,服務器就回應一個“304 Not Modified”,表示緩存依然有效,瀏覽器就可以更新一下有效期,然后放心大膽地使用緩存了。

代理服務器代理服務器就是客戶端和服務端之間的中間商,在中間的位置轉(zhuǎn)發(fā)上游的請求和下游的響應。代理服務器在計算機領(lǐng)域有非常重要的功能:

1.負載均衡:面向客戶端時屏蔽原服務器,代理服務器可以通過輪詢、哈希等算法將流量分發(fā),提高整體的性能。

2.健康檢查:使用‘心跳’等機制監(jiān)控服務器,保證服務器的可用性。

3.安全防護:保護被代理服務端的IP和流量,防止網(wǎng)絡(luò)攻擊或負載問題。

4.加密卸載:對外和對內(nèi)使用不同的加密策略,節(jié)省加密成本

5.內(nèi)容緩存:暫存/復位服務器的響應。

緩存代理

HTTP的服務端緩存主要由代理服務器來實現(xiàn),代理服務器收到源服務器的響應之后將報文轉(zhuǎn)發(fā)給客戶端的同時也存入自己的cache里,下次再有相同的請求就可以直接發(fā)送304或者緩存數(shù)據(jù),節(jié)省源服務器的成本。

因為代理服務器既是服務端,又是客戶端的特性,有一些特殊的cache-control屬性:

1.服務端

private: 表示只能客戶端緩存,不允許代理服務器上緩存。
punlic:表示完全公開,客戶端和代理服務器都可以緩存。
proxy-revalidate:要求代理服務器緩存過期后必須回源驗證。
s-maxage: 代理服務器緩存的有效期no-transform: 不允許代理服務器轉(zhuǎn)換數(shù)據(jù)格式。

2.客戶端

max-stale: 如果代理上的緩存過期了也可以接受,但不能過期太多,超過 x 秒也會不要。
min-flash: 表示緩存少于x有效期就不要了。only-if-cached:表示只接受代理緩存的數(shù)據(jù),不接受源服務器的響應。如果代理上沒有緩存或者緩存過期,就應該給客戶端返回一個 504。

HTTPS

由于 HTTP 天生“明文”的特點,整個傳輸過程完全透明,任何人都能夠在鏈路中截獲、修改或者偽造請求 / 響應報文,數(shù)據(jù)不具有可信性。只有具有機密性、完整性、身份認證和不可否認性,我們才認為這個請求是安全的。HTTPS為HTTP增加了以上四個特性。

HTTPS實際上就指的是HTTP over TLS/SSl。是在原本的HTTP協(xié)議上加了一層TLS/SSL協(xié)議。

(一)SSL/TLS

SSL 即安全套接層(Secure Sockets Layer),在 OSI 模型中處于第 5 層(會話層),由網(wǎng)景公司于 1994 年發(fā)明。SSL 發(fā)展到 v3 時已經(jīng)證明了它自身是一個非常好的安全通信協(xié)議,于是在 1999 年它改名為 TLS(傳輸層安全, Transport Layer Security),目前應用的最廣泛的 TLS 是 1.2,而之前的協(xié)議(TLS1.1/1.0、SSLv3/v2)都已經(jīng)被認為是不安全的。

SSL/TLS通過加密(encrypt)來傳輸密文(cipher text)保證數(shù)據(jù)傳輸?shù)陌踩?,只有擁有密鑰(key)的人才能夠通過解密(decrypt)獲得明文(plain text/clear text),加密解密的操作過程就是加密算法。所以“密鑰”是一長串的數(shù)字,約定俗成的度量單位是“位”(bit)。比如,說密鑰長度是 128,就是 16 字節(jié)的二進制串,密鑰長度 1024,就是 128 字節(jié)的二進制串。按照密鑰的使用方式,加密可以分為兩大類:對稱加密和非對稱加密。

對稱加密

顧名思義,加密解密都使用相同的密鑰就叫做對稱加密。TLS里目前常用的有 AES 和 ChaCha20。

AES 的意思是“高級加密標準”(Advanced Encryption Standard),密鑰長度可以是 128、192 或 256。它是 DES 算法的替代者,安全強度很高,性能也很好,而且有的硬件還會做特殊優(yōu)化,所以非常流行,是應用最廣泛的對稱加密算法。

ChaCha20 是 Google 設(shè)計的另一種加密算法,密鑰長度固定為 256 位,純軟件運行性能要超過 AES,曾經(jīng)在移動客戶端上比較流行,但 ARMv8 之后也加入了 AES 硬件優(yōu)化,所以現(xiàn)在不再具有明顯的優(yōu)勢。

非對稱加密

對稱加密看上去很好的實現(xiàn)了機密性,但是還有一個問題就是如何安全的傳輸密鑰。因為在加密算法中,只要擁有密鑰就可以解密,如果密鑰在傳輸過程中被竊取,也就無機密性可言。為了解決這個問題,又有了非對稱加密算法。他擁有兩個密鑰,分別是公鑰(public key)和私鑰(private key),公鑰是公開的,而私鑰是嚴格保密的。公鑰和私鑰有個特別的“單向”性,雖然都可以用來加密解密,但公鑰加密后只能用私鑰解密,反過來,私鑰加密后也只能用公鑰解密。非對稱加密可以解決密鑰交換的問題。網(wǎng)站秘密保管私鑰,在網(wǎng)上任意分發(fā)公鑰,你想要登錄網(wǎng)站只要用公鑰加密就行了,密文只能由私鑰持有者才能解密。而黑客因為沒有私鑰,所以就無法破解密文。

非對稱加密算法的設(shè)計要比對稱算法難得多,在 TLS 里只有很少的幾種,比如 DH、DSA、RSA、ECC 等。

RSA 可能是其中最著名的一個,幾乎可以說是非對稱加密的代名詞,它的安全性基于“整數(shù)分解”的數(shù)學難題,使用兩個超大素數(shù)的乘積作為生成密鑰的材料,想要從公鑰推算出私鑰是非常困難的。

ECC是非對稱加密里的“后起之秀”,它基于“橢圓曲線離散對數(shù)”的數(shù)學難題,使用特定的曲線方程和基點生成公鑰和私鑰,子算法 ECDHE 用于密鑰交換,ECDSA 用于數(shù)字簽名。相對RSA,ECC在安全和性能上都有更明顯的優(yōu)勢,160位的ECC相當于1024位的RSA,260位的ECC相當于2048位的RSA。

混合加密雖然非對稱加密沒有密鑰交換的難題,但因為它們都是基于復雜的數(shù)學難題,運算速度很慢,即使是 ECC 也要比 AES 差上好幾個數(shù)量級。所以目前TLS使用混合加密,使二者取長補短,既能高效加密解密,又能安全的進行數(shù)據(jù)傳輸。

在建立連接之初先使用非對稱加密的形式傳遞密鑰,然后用隨機數(shù)產(chǎn)生對稱算法使用的“會話密鑰”(session key),再用公鑰加密。因為會話密鑰很短,通常只有 16 字節(jié)或 32 字節(jié),所以慢一點也無所謂。對方拿到密文后用私鑰解密,取出會話密鑰。這樣,雙方就實現(xiàn)了對稱密鑰的安全交換,后續(xù)就不再使用非對稱加密,全都使用對稱加密。

摘要算法

實現(xiàn)完整性的手段主要是摘要算法(Digest Algorithm),也就是常說的散列函數(shù)、哈希函數(shù)(Hash Function)。可以把摘要算法近似地理解成一種特殊的加密算法,它能夠把任意長度的數(shù)據(jù)加密成固定長度、而且獨一無二的“摘要”字符串,且不能從壓縮后的密文中推導出原文。MD5(Message-Digest 5)、SHA-1(Secure Hash Algorithm 1就是最常用的兩個摘要算法,能夠生成 16 字節(jié)和 20 字節(jié)長度的數(shù)字摘要。但這兩個算法的安全強度比較低,不夠安全,在 TLS 里已經(jīng)被禁止使用了。目前TLS使用的是SLA-2。摘要算法保證了“數(shù)字摘要”和原文是完全等價的。所以,我們只要在原文后附上它的摘要,就能夠保證數(shù)據(jù)的完整性。不過摘要算法不具有機密性,所以真正的完整性還是需要建立在機密性之上。

數(shù)字簽名數(shù)字簽名的原理其實很簡單,就是把公鑰私鑰的用法反過來,之前是公鑰加密、私鑰解密,現(xiàn)在是私鑰加密、公鑰解密。但又因為非對稱加密效率太低,所以私鑰只加密原文的摘要,這樣運算量就小的多,而且得到的數(shù)字簽名也很小,方便保管和傳輸。數(shù)字證書和CA

因為公鑰是任何人都可以發(fā)布的,所以我們需要引入第三方來保證公鑰的可信度,這個“第三方”就是我們常說的 CA(Certificate Authority,證書認證機構(gòu)),CA 對公鑰的簽名認證也是有格式的,要包含公鑰的序列號、用途、頒發(fā)者、有效時間等等,把這些打成一個包再簽名,完整地證明公鑰關(guān)聯(lián)的各種信息,形成“數(shù)字證書”(Certificate)。小一點的 CA 可以讓大 CA 簽名認證,但鏈條的最后,也就是 Root CA,就只能自己證明自己了,這個就叫“自簽名證書”(Self-Signed Certificate)或者“根證書”(Root Certificate)。你必須相信,否則整個證書信任鏈就走不下去了。

(二)TLS1.2建立連接的過程

記錄協(xié)議(Record Protocol): 規(guī)定了 TLS 收發(fā)數(shù)據(jù)的基本單位:記錄(record)。所有的其他子協(xié)議都需要通過記錄協(xié)議發(fā)出,但多個記錄數(shù)據(jù)可以在一個 TCP 包里一次性發(fā)出。

警報協(xié)議(Alert Protocol): 的職責是向?qū)Ψ桨l(fā)出警報信息,有點像是 HTTP 協(xié)議里的狀態(tài)碼。比如,protocol_version 就是不支持舊版本,bad_certificate 就是證書有問題,收到警報后另一方可以選擇繼續(xù),也可以立即終止連接。

握手協(xié)議(Handshake Protocol): 是 TLS 里最復雜的子協(xié)議,要比 TCP 的 SYN/ACK 復雜的多,瀏覽器和服務器會在握手過程中協(xié)商 TLS 版本號、隨機數(shù)、密碼套件等信息,然后交換證書和密鑰參數(shù),最終雙方協(xié)商得到會話密鑰,用于后續(xù)的混合加密系統(tǒng)。

變更密碼規(guī)范協(xié)議(Change Cipher Spec Protocol): 是一個“通知”,告訴對方,后續(xù)的數(shù)據(jù)都將使用加密保護。那么反過來,在它之前,數(shù)據(jù)都是明文的。



(三)TLS1.3



HTTP/2

HTTP1.X引入了Cookie解決了無狀態(tài)的問題、通過引入TLS/SSL解決了明文傳輸不安全的問題。那接下來HTTP2的發(fā)力點就放在性能層面了。Google首先發(fā)明了SPDY協(xié)議,隨后互聯(lián)網(wǎng)標準化組織IETF以SPDY 為基礎(chǔ)發(fā)布了HTTP2。HTTP2對于性能上的優(yōu)化主要由以下幾點出發(fā):1. 包頭過大 2. 隊頭阻塞 。

(一)性能優(yōu)化

在HTTP1.x時期,很多請求請求體和響應體的大小遠遠小于頭部字段的大小,比如GET請求,301/302/204響應。而且很多頭部字段是重復的,HTTP/1.x浪費了大量的帶寬在傳輸重復的頭字段上,所以,HTTP/2 把“頭部壓縮”作為性能改進的一個重點。

HPACK算法是專門為壓縮 HTTP 頭部定制的算法,與 gzip、zlib 等壓縮算法不同,它是一個“有狀態(tài)”的算法,需要客戶端和服務器各自維護一份“索引表”,壓縮和解壓縮就是查表和更新表的操作。為了方便管理和壓縮,HTTP/2 廢除了原有的起始行概念,把起始行里面的請求方法、URI、狀態(tài)碼等統(tǒng)一轉(zhuǎn)換成了頭字段的形式, 為了與“真頭字段”區(qū)分開來,這些“偽頭字段”會在名字前加一個“:”,比如“:authority” “:method” “:status”,分別表示的是域名、請求方法和狀態(tài)碼。廢除了起始行里的版本號和錯誤原因短語。用索引號表示重復的字符串,還釆用哈夫曼編碼來壓縮整數(shù)和字符串,可以達到 50%~90% 的高壓縮率。

下面的這個表格列出了“靜態(tài)表”的一部分,這樣只要查表就可以知道字段名和對應的值,比如數(shù)字“2”代表“GET”,數(shù)字“8”代表狀態(tài)碼 200。

新增的頭字段或者值保存在動態(tài)表(Dynamic Table)里,它添加在靜態(tài)表后面,結(jié)構(gòu)相同,但會在編碼解碼的時候隨時更新。比如說,第一次發(fā)送請求時的“user-agent”字段長是一百多個字節(jié),用哈夫曼壓縮編碼發(fā)送之后,客戶端和服務器都更新自己的動態(tài)表,添加一個新的索引號“65”。那么下一次發(fā)送的時候就不用再重復發(fā)那么多字節(jié)了,只要用一個字節(jié)發(fā)送編號就好。

基于請求-應答模式的http協(xié)議存在隊頭阻塞的問題,前面提到的并發(fā)連接和域名分片都是犧牲數(shù)量解決質(zhì)量的思路。而HTTP2采用了二進制分幀?流式傳輸?shù)姆绞絹斫鉀Q這個問題。

二進制分幀

HTTP/2把原來的Header+Body的消息“打散”為數(shù)個小片的二進制“幀”(Frame),用HEADER幀存放頭數(shù)據(jù)、DATA幀存放實體數(shù)據(jù)。

流式傳輸

HTTP/2還定義了一個“流”(Stream)的概念,它是二進制幀的雙向傳輸序列,同一個消息往返的幀會分配一個唯一的流 ID。你可以把它想象成是一個虛擬的“數(shù)據(jù)流”,在里面流動的是一串有先后順序的數(shù)據(jù)幀,這些數(shù)據(jù)幀按照次序組裝起來就是HTTP/1里的請求報文和響應報文。HTTP/2 可以在一個 TCP 連接上用“流”同時發(fā)送多個“碎片化”的消息,這就是常說的“多路復用”( Multiplexing),多個往返通信都復用一個連接來處理。在“流”的層面上看,消息是一些有序的“幀”序列,而在“連接”的層面上看,消息卻是亂序收發(fā)的“幀”。多個請求 / 響應之間沒有了順序關(guān)系,不需要排隊等待,也就不會再出現(xiàn)“隊頭阻塞”問題,降低了延遲,大幅度提高了連接的利用率。

幀開頭是幀長度(不包含報文頭的9個字節(jié)),默認上限是2^14,最大是2^24,也就是說 HTTP/2的幀通常不超過16K,最大是 16M。

后面的一個字節(jié)是幀類型,大致可以分成數(shù)據(jù)幀和控制幀兩類,HEADERS幀和DATA幀屬于數(shù)據(jù)幀,存放的是 HTTP 報文,而 SETTINGS、PING、PRIORITY 等則是用來管理流的控制幀。

第 5 個字節(jié)是非常重要的幀標志信息,可以保存 8 個標志位,攜帶簡單的控制信息。常用的標志位有 END_HEADERS 表示頭數(shù)據(jù)結(jié)束,END_STREAM 表示單方向數(shù)據(jù)發(fā)送結(jié)束(即 EOS,End of Stream)。

報文頭里最后 4 個字節(jié)是流標識符,也就是幀所屬的“流”,接收方使用它就可以從亂序的幀里識別出具有相同流 ID 的幀序列(在 HTTP/2 連接上,雖然幀是亂序收發(fā)的,但只要它們都擁有相同的流 ID,就都屬于一個流,而且在這個流里幀不是無序的,而是有著嚴格的先后順序。),按順序組裝起來就實現(xiàn)了虛擬的“流”。流標識符雖然有 4 個字節(jié),但最高位被保留不用,所以只有 31 位可以使用,也就是說,流標識符的上限是 2^31,大約是 21 億。

流的特點

1.流是可并發(fā)的,一個 HTTP/2 連接上可以同時發(fā)出多個流傳輸數(shù)據(jù),也就是并發(fā)多請求,實現(xiàn)“多路復用”。

2.客戶端和服務器都可以創(chuàng)建流,雙方互不干擾。

3.流是雙向的,一個流里面客戶端和服務器都可以發(fā)送或接收數(shù)據(jù)幀,也就是一個“請求 - 應答”來回。

4.流之間沒有固定關(guān)系,彼此獨立,但流內(nèi)部的幀是有嚴格順序的。

5.流可以設(shè)置優(yōu)先級,讓服務器優(yōu)先處理,比如先傳 HTML/CSS,后傳圖片,優(yōu)化用戶體驗。

6.流 ID 不能重用,只能順序遞增,客戶端發(fā)起的 ID 是奇數(shù),服務器端發(fā)起的 ID 是偶數(shù)。

7.在流上發(fā)送“RST_STREAM”幀可以隨時終止流,取消接收或發(fā)送。

8.第 0 號流比較特殊,不能關(guān)閉,也不能發(fā)送數(shù)據(jù)幀,只能發(fā)送控制幀,用于流量控制。



HTTP/3

HTTP/2 雖然使用“幀”、“流”、“多路復用”,沒有了“隊頭阻塞”,但這些手段都是在應用層里,而在 TCP 協(xié)議里,還是會發(fā)生“隊頭阻塞”。Google 在推 SPDY 的時候就已經(jīng)意識到了這個問題,于是就又發(fā)明了一個新的QUIC協(xié)議,讓 HTTP 跑在 QUIC 上而不是 TCP 上。而這個HTTP over QUIC就是 HTTP 協(xié)議的下一個大版本,HTTP/3。它在 HTTP/2 的基礎(chǔ)上又實現(xiàn)了質(zhì)的飛躍,真正完美地解決了隊頭阻塞問題。

(一)QUICK

QUIC 基于 UDP,而 UDP 是“無連接”的,不需要“握手”和“揮手”,所以天生就要比 TCP 快。QUIC 全面采用加密通信,它使用自己的幀“接管”了 TLS 里的“記錄”,握手消息、警報消息都不使用 TLS 記錄,直接封裝成 QUIC 的幀發(fā)送,省掉了一次開銷。QUIC 的基本數(shù)據(jù)傳輸單位是包(packet)和幀(frame),一個包由多個幀組成,包面向的是“連接”,幀面向的是“流”。

QUIC 使用不透明的“連接 ID”來標記通信的兩個端點,客戶端和服務器可以自行選擇一組 ID 來標記自己,這樣就解除了 TCP 里連接對“IP 地址 + 端口”(即常說的四元組)的強綁定,支持“連接遷移”(Connection Migration)。

(二)HTTP/3

因為 QUIC 本身就已經(jīng)支持了加密、流和多路復用,所以HTTP/3不需要定義流,而是直接使用 QUIC 的流。由于流管理被“下放”到了 QUIC,所以 HTTP/3 里幀的結(jié)構(gòu)也變簡單了。幀頭只有兩個字段:類型和長度,而且同樣都采用變長編碼,最小只需要兩個字節(jié)。

推薦閱讀

快收藏!最全GO語言實現(xiàn)設(shè)計模式

可能是最全的數(shù)據(jù)倉庫全景科普和開發(fā)方法論!

深入淺出帶你走進Redis!

CPU如何與內(nèi)存交互?



關(guān)鍵詞:深入

74
73
25
news

版權(quán)所有? 億企邦 1997-2025 保留一切法律許可權(quán)利。

為了最佳展示效果,本站不支持IE9及以下版本的瀏覽器,建議您使用谷歌Chrome瀏覽器。 點擊下載Chrome瀏覽器
關(guān)閉