Http協議那些事兒

來源於codesheep,對其文章美化(包括但不限於文字刪減,排版)。

{% note danger %}

01 HTTP 基本概念

{% endnote %}
HTTP 是超文本傳輸協議,是超文本傳輸協議,也就是 H yperText T ransfer P rotocol。HTTP的名字「超文本協議傳輸」,它可以拆成三個部分:

    超文本

    傳輸

    協議

三個部分

說白了,HTTP 是一個在計算機世界裏專門在「兩點」之間「傳輸」文字、圖片、音頻、視頻等「超文本」數據的「約定和規範」

請求 - 應答

{% note success %}

02 HTTP 常見的狀態碼

{% endnote %}

1xx

1xx 類狀態碼屬於提示信息,是協議處理中的一種中間狀態,實際用到的比較少。

2xx

2xx 類狀態碼錶示服務器成功處理了客戶端的請求,也是我們最願意看到的狀態。

  • 200 OK」是最常見的成功狀態碼,表示一切正常。如果是非 HEAD 請求,服務器返回的響應頭都會有 body 數據。

  • 204 No Content」也是常見的成功狀態碼,與 200 OK 基本相同,但響應頭沒有 body 數據。

  • 206 Partial Content」是應用於 HTTP 分塊下載或斷電續傳,表示響應返回的 body 數據並不是資源的全部,而是其中的一部分,也是服務器處理成功的狀態。

3xx

3xx 類狀態碼錶示客戶端請求的資源發送了變動,需要客戶端用新的 URL 重新發送請求獲取資源,也就是重定向。

  • 301 Moved Permanently」表示永久重定向,說明請求的資源已經不存在了,需改用新的 URL 再次訪問。

  • 302 Found」表示臨時重定向,說明請求的資源還在,但暫時需要用另一個 URL 來訪問。301 和 302 都會在響應頭裏使用字段 Location,指明後續要跳轉的 URL,瀏覽器會自動重定向新的 URL。

  • 304 Not Modified」不具有跳轉的含義,表示資源未修改,重定向已存在的緩衝文件,也稱緩存重定向,用於緩存控制。

4xx

4xx類狀態碼錶示客戶端發送的報文有誤,服務器無法處理,也就是錯誤碼的含義。

  • 400 Bad Request」表示客戶端請求的報文有錯誤,但只是個籠統的錯誤。

  • 403 Forbidden」表示服務器禁止訪問資源,並不是客戶端的請求出錯。

  • 404 Not Found」表示請求的資源在服務器上不存在或未找到,所以無法提供給客戶端。

5xx

5xx 類狀態碼錶示客戶端請求報文正確,但是服務器處理時內部發生了錯誤,屬於服務器端的錯誤碼。

  • 500 Internal Server Error」與 400 類型,是個籠統通用的錯誤碼,服務器發生了什麼錯誤,我們並不知道。

  • 501 Not Implemented」表示客戶端請求的功能還不支持,類似“即將開業,敬請期待”的意思。

  • 502 Bad Gateway」通常是服務器作爲網關或代理時返回的錯誤碼,表示服務器自身工作正常,訪問後端服務器發生了錯誤。

  • 503 Service Unavailable」表示服務器當前很忙,暫時無法響應服務器,類似“網絡服務正忙,請稍後重試”的意思。

{% note success %}

03 HTTP 常見字段

{% endnote %}

1. Host字段

客戶端發送請求時,用來指定服務器的域名。

    Host: www.A.com

有了 Host 字段,就可以將請求發往「同一臺」服務器上的不同網站。

2.Content-Length 字段

服務器在返回數據時,會有Content-Length 字段,表明本次迴應的數據長度。

    Content-Length: 1000

如上面則是告訴瀏覽器,本次服務器迴應的數據長度是 1000 個字節,後面的字節就屬於下一個迴應了。

3.Connection 字段

Connection字段最常用於客戶端要求服務器使用 TCP 持久連接,以便其他請求複用。HTTP/1.1 版本的默認連接都是持久連接,但爲了兼容老版本的 HTTP,需要指定 Connection 首部字段的值爲 Keep-Alive

    Connection: keep-alive

一個可以複用的 TCP 連接就建立了,直到客戶端或服務器主動關閉連接。但是,這b並不是標準字段。

4.Content-Type 字段

Content-Type字段用於服務器迴應時,告訴客戶端,本次數據是什麼格式。

    Content-Type: text/html; charset=utf-8

上面的類型表明,發送的是網頁,而且編碼是UTF-8。客戶端請求的時候,可以使用 Accept 字段聲明自己可以接受哪些數據格式。

    Accept: */*

上面代碼中,客戶端聲明自己可以接受任何格式的數據。

5.Content-Encoding 字段

Content-Encoding字段說明數據的壓縮方法。表示服務器返回的數據使用了什麼壓縮格式

    Content-Encoding: gzip

上面表示服務器返回的數據採用了 gzip 方式壓縮,告知客戶端需要用此方式解壓。
客戶端在請求時,用 Accept-Encoding 字段說明自己可以接受哪些壓縮方法。

    Accept-Encoding: gzip, deflate

{% note success %}

05 GET 與 POST

{% endnote %}

GET 和 POST 的區別

Get 方法的含義是請求 從服務器獲取資源 ,這個資源可以是靜態的文本、頁面、圖片視頻等。比如,你打開我的文章,瀏覽器就會發送 GET 請求給服務器,服務器就會返回文章的所有文字及資源。

POST方法則是相反操作,它向URI 指定的資源提交數據,數據就放在報文body裏。

比如,你在我文章底部,敲入了留言後點擊「提交」( 暗示你們留言 ),瀏覽器就會執行一次 POST 請求,把你的留言文字放進了報文 body 裏,然後拼接好 POST 請求頭,通過 TCP 協議發送給服務器。

GET 和 POST 的安全和冪等

--------chuyuxuan: 講真,我頭一次聽說安全和冪等

安全和冪等:

  • HTTP協議裏,所謂的「安全」是指請求方法不會「破壞」服務器上的資源。
  • 所謂的「冪等」,意思是多次執行相同的操作,結果都是「相同」的。

那麼很明顯 :

  • GET 方法就是安全且冪等的 ,因爲它是「只讀」操作,無論操作多少次,服務器上的數據都是安全的,且每次的結果都是相同的。

  • POST 因爲是「新增或提交數據」的操作,會修改服務器上的資源,所以是 不安全 的,且多次提交數據就會創建多個資源,所以 不是冪等 的。

{% note success %}

06 HTTP 特性

{% endnote %}

優點

HTTP 最凸出的優點是「簡單、靈活和易於擴展、應用廣泛和跨平臺」。

-------chuyuxuan: 怪不得有人說以後BS(browser clinet)架構要廣泛於CS 架構.

1. 簡單

HTTP 基本的報文格式就是header + body,頭部信息也是 key-value 簡單文本的形式, 易於理解 ,降低了學習和使用的門檻。

2. 靈活和易於擴展

HTTP協議裏的各類請求方法、URI/URL、狀態碼、頭字段等每個組成要求都沒有被固定死,都允許開發人員 自定義和擴充

同時 HTTP 由於是工作在應用層( OSI 第七層),則它 下層可以隨意變化

HTTPS 也就是在 HTTP 與 TCP 層之間增加了 SSL/TLS 安全傳輸層,HTTP/3 甚至把 TCPP 層換成了基於 UDP 的 QUIC。

3. 應用廣泛和跨平臺

互聯網發展至今,HTTP 的應用範圍非常的廣泛,從臺式機的瀏覽器到手機上的各種 APP,從看新聞、刷貼吧到購物、理財、吃雞,HTTP 的應用 片地開花 ,同時天然具有 跨平臺 的優越性。

缺點

HTTP 協議裏有優缺點一體的 雙刃劍 ,分別是「無狀態、明文傳輸」,同時還有一大缺點「不安全」。

1. 無狀態雙刃劍

無狀態的 好處 ,因爲服務器不會去記憶 HTTP 的狀態,所以不需要額外的資源來記錄狀態信息,這能減輕服務器的負擔,能夠把更多的 CPU 和內存用來對外提供服務。

無狀態的 壞處 ,既然服務器沒有記憶能力,它在完成有關聯性的操作時會非常麻煩。

例如:登錄;添加購物車;下單;結算;支付,這系列操作都要知道用戶的身份才行。但服務器不知道這些請求是有關聯的,每次都要問一遍身份信息。
這樣每操作一次,都要驗證信息,這樣的購物體驗還能愉快嗎?

對於無狀態的問題,解法方案有很多種,其中比較簡單的方式用 Cookie 技術。

Cookie 通過在請求和響應報文中寫入 Cookie 信息來控制客戶端的狀態。

相當於, 在客戶端第一次請求後,服務器會下發一個裝有客戶信息的「小貼紙」,後續客戶端請求服務器的時候,帶上「小貼紙」,服務器就能認得了了 .

2. 明文傳輸雙刃劍

明文意味着在傳輸過程中的信息,是可方便閱讀的,通過瀏覽器的 F12 控制檯或Wireshark 抓包都可以直接肉眼查看,爲我們調試工作帶了極大的便利性。

但是這正是這樣,HTTP 的所有信息都暴露在了光天化日下,相當於 信息裸奔 。在傳輸的漫長的過程中,信息的內容都毫無隱私可言,很容易就能被竊取,如果裏面有你的賬號密碼信息,那 你號沒了

3. 不安全

HTTP 比較嚴重的缺點就是不安全:

  • 通信使用明文(不加密),內容可能會被竊聽。比如, 賬號信息容易泄漏,那你號沒了。
  • 不驗證通信方的身份,因此有可能遭遇僞裝。比如, 訪問假的淘寶、拼多多,那你錢沒了。
  • 無法證明報文的完整性,所以有可能已遭篡改。比如, 網頁上植入垃圾廣告,視覺污染,眼沒了。

HTTP 的安全問題,可以用HTTPS的方式解決,也就是通過引入SSL/TLS 層,使得在安全上達到了極致。

-------chuyuxuan: 比方說我的博客就是採用https加密的.

{% note success %}

07 HTTP 性能消耗

{% endnote %}

HTTP 協議是基於 TCP/IP ,並且使用了「 請求 - 應答 」的通信模式,所以性能的關鍵就在這 兩點 裏。

1. 長連接

早期 HTTP/1.0 性能上的一個很大的問題,那就是每發起一個請求,都要新建一次 TCP 連接(三次握手),而且是串行請求,做了無畏的 TCP 連接建立和斷開,增加了通信開銷。

爲了解決上述 TCP 連接問題,HTTP/1.1 提出了 長連接 的通信方式,也叫持久連接。這種方式的好處在於減少了 TCP 連接的重複建立和斷開所造成的額外開銷,減輕了服務器端的負載。

持久連接的特點是,只要任意一端沒有明確提出斷開連接,則保持 TCP 連接狀態。

2. 管道網絡傳輸

HTTP/1.1 採用了長連接的方式,這使得管道(pipeline)網絡傳輸成爲了可能。

即可在同一個 TCP 連接裏面,客戶端可以發起多個請求,只要第一個請求發出去了,不必等其回來,就可以發第二個請求出去,可以 減少整體的響應時間。

舉例來說,客戶端需要請求兩個資源。以前的做法是,在同一個TCP連接裏面,先發送 A 請求,然後等待服務器做出迴應,收到後再發出 B 請求。管道機制則是允許瀏覽器同時發出 A 請求和 B 請求。

但是服務器還是按照 順序 ,先回應 A 請求,完成後再回應 B 請求。要是 前面的迴應特別慢,後面就會有許多請求排隊等着。這稱爲「隊頭堵塞」。

3. 隊頭阻塞

請求 - 應答」的模式加劇了 HTTP 的性能問題。

因爲當順序發送的請求序列中的一個請求因爲某種原因被阻塞時,在後面排隊的所有請求也一同被阻塞了,會招致客戶端一直請求不到數據,這也就是「 隊頭阻塞 」。 好比上班的路上塞車

總之 HTTP/1.1 的性能一般般,後續的 HTTP/2 和 HTTP/3 就是在優化 HTTP 的性能。

{% note success %}

08 HTTP 與 HTTPS

{% endnote %}

    1. HTTP 是超文本傳輸協議,信息是明文傳輸,存在安全風險的問題。HTTPS 則解決 HTTP 不安全的缺陷,在 TCP 和 HTTP 網絡層之間加入了 SSL/TLS 安全協議,使得報文能夠加密傳輸。
    1. HTTP 連接建立相對簡單, TCP 三次握手之後便可進行 HTTP 的報文傳輸。而 HTTPS 在 TCP 三次握手之後,還需進行 SSL/TLS 的握手過程,纔可進入加密報文傳輸。
    1. HTTP 的端口號是80,HTTPS 的端口號是 443
    1. HTTPS 協議需要向 CA(證書權威機構)申請數字證書,來保證服務器的身份是可信的。

HTTPS --VS-- HTTP

HTTP 三個風險:

  • 竊聽風險 ,比如通信鏈路上可以獲取通信內容,用戶號容易沒。
  • 篡改風險 ,比如強制入垃圾廣告,視覺污染,用戶眼容易瞎。
  • 冒充風險 ,比如冒充淘寶網站,用戶錢容易沒。

HTTPS 三個優點:

  • 信息加密 :交互信息無法被竊取,但你的號會因爲「自身忘記」賬號而沒。

  • 校驗機制 :無法篡改通信內容,篡改了就不能正常顯示,但百度「競價排名」依然可以搜索垃圾廣告。

  • 身份證書 :證明淘寶是真的淘寶網,但你的錢還是會因爲「剁手」而沒。

可見,只要自身不做「惡」,SSL/TLS 協議是能保證通信是安全的。

HTTPS 解決 HTTP

1. 混合加密

通過 混合加密 的方式可以保證信息的 機密性 ,解決了竊聽的風險。

HTTPS 採用的是 對稱加密非對稱加密 結合的「混合加密」方式:

  • 在通信建立前採用 非對稱加密 的方式交換「會話祕鑰」,後續就不再使用非對稱加密。
  • 在通信過程中全部使用 對稱加密 的「會話祕鑰」的方式加密明文數據。

採用「混合加密」的方式的原因:

  • 對稱加密 只使用一個密鑰,運算速度快,密鑰必須保密,無法做到安全的密鑰交換。
  • 非對稱加密 使用兩個密鑰:公鑰和私鑰,公鑰可以任意分發而私鑰保密,解決了密鑰交換問題但速度慢。

2. 摘要算法

摘要算法 用來實現 完整性 ,能夠爲數據生成獨一無二的「指紋」,用於校驗數據的完整性,解決了篡改的風險。

校驗完整性

客戶端在發送明文之前會通過摘要算法算出明文的「指紋」,發送的時候把「指紋 + 明文」一同加密成密文後,發送給服務器,服務器解密後,用相同的摘要算法算出發送過來的明文,通過比較客戶端攜帶的「指紋」和當前算出的「指紋」做比較,若「指紋」相同,說明數據是完整的。

3. 數字證書

客戶端先向服務器端索要公鑰,然後用公鑰加密信息,服務器收到密文後,用自己的私鑰解密。

這就存在些問題,如何保證公鑰不被篡改和信任度?

所以這裏就需要藉助第三方權威機構 CA (數字證書認證機構),將 服務器公鑰放在數字證書 (由數字證書認證機構頒發)中,只要證書是可信的,公鑰就是可信的。

數字證書工作流程

通過數字證書的方式保證服務器公鑰的身份,解決冒充的風險。

{% note success %}

09 HTTPS 的連接交互

{% endnote %}

SSL/TLS 協議基本流程:

  • 客戶端向服務器索要並驗證服務器的公鑰。
  • 雙方協商生產「會話祕鑰」。
  • 雙方採用「會話祕鑰」進行加密通信。

前兩步也就是 SSL/TLS 的建立過程,也就是握手階段。

SSL/TLS 的「握手階段」涉及 四次 通信,可見下圖:

HTTPS 連接建立過程

SSL/TLS 協議建立的詳細流程:

1. ClientHello

首先,由客戶端向服務器發起加密通信請求,也就是 ClientHello 請求。

在這一步,客戶端主要向服務器發送以下信息:

(1)客戶端支持的 SSL/TLS 協議版本,如 TLS 1.2 版本。

(2)客戶端生產的隨機數(Client Random),後面用於生產「會話祕鑰」。

(3)客戶端支持的密碼套件列表,如 RSA 加密算法。

2. SeverHello

服務器收到客戶端請求後,向客戶端發出響應,也就是 SeverHello。服務器迴應的內容有如下內容:

  • (1)確認 SSL/ TLS 協議版本,如果瀏覽器不支持,則關閉加密通信。

  • (2)服務器生產的隨機數(Server Random),後面用於生產「會話祕鑰」。

  • (3)確認的密碼套件列表,如 RSA 加密算法。

  • (4)服務器的數字證書。

3.客戶端迴應

客戶端收到服務器的迴應之後,首先通過瀏覽器或者操作系統中的 CA 公鑰,確認服務器的數字證書的真實性。

如果證書沒有問題,客戶端會從數字證書中取出服務器的公鑰,然後使用它加密報文,向服務器發送如下信息:

  • (1)一個隨機數(pre-master key)。該隨機數會被服務器公鑰加密。

  • (2)加密通信算法改變通知,表示隨後的信息都將用「會話祕鑰」加密通信。

  • (3)客戶端握手結束通知,表示客戶端的握手階段已經結束。這一項同時把之前所有內容的發生的數據做個摘要,用來供服務端校驗。

上面第一項的隨機數是整個握手階段的第三個隨機數,這樣服務器和客戶端就同時有三個隨機數,接着就用雙方協商的加密算法, 各自生成 本次通信的「會話祕鑰」。

4. 服務器的最後迴應

服務器收到客戶端的第三個隨機數(pre-master key)之後,通過協商的加密算法,計算出本次通信的「會話祕鑰」。然後,向客戶端發生最後的信息:

  • (1)加密通信算法改變通知,表示隨後的信息都將用「會話祕鑰」加密通信。

  • (2)服務器握手結束通知,表示服務器的握手階段已經結束。這一項同時把之前所有內容的發生的數據做個摘要,用來供客戶端校驗。

至此,整個 SSL/TLS 的握手階段全部結束。接下來,客戶端與服務器進入加密通信,就完全是使用普通的 HTTP 協議,只不過用「會話祕鑰」加密內容。

{% note success %}

10 HTTP/1.1、HTTP/2、HTTP/3 演變

{% endnote %}

HTTP/1.1 相比 HTTP/1.0 性能上的改進:

  • 使用 TCP 長連接的方式改善了 HTTP/1.0 短連接造成的性能開銷。
  • 支持 管道(pipeline)網絡傳輸,只要第一個請求發出去了,不必等其回來,就可以發第二個請求出去,可以減少整體的響應時間。

但 HTTP/1.1 還是有性能瓶頸

  • 請求 / 響應頭部(Header)未經壓縮就發送,首部信息越多延遲越大。只能壓縮 Body 的部分;
  • 發送冗長的首部。每次互相發送相同的首部造成的浪費較多;
  • 服務器是按請求的順序響應的,如果服務器響應慢,會招致客戶端一直請求不到數據,也就是隊頭阻塞;
  • 沒有請求優先級控制;
  • 請求只能從客戶端開始,服務器只能被動響應。

HTTP/2 相比 HTTP/1.1 性能上的改進

HTTP/2協議是基於 HTTPS的,所以 HTTP/2 的安全性也是有保障的。

1. 頭部壓縮

HTTP/2壓縮頭 (Header)如果你同時發出多個請求,他們的頭是一樣的或是相似的,那麼,協議會幫你 消除重複的分

這就是所謂的HPACK 算法:在客戶端和服務器同時維護一張頭信息表,所有字段都會存入這個表,生成一個索引號,以後就不發送同樣字段了,只發送索引號,這樣就 提高速度 了。

2. 二進制格式

HTTP/2 不再像HTTP/1.1裏的純文本形式的報文,而是全面採用了 二進制格式。

頭信息和數據體都是二進制,並且統稱爲幀(frame): 頭信息幀和數據幀

報文區別

這樣雖然對人不友好,但是對計算機非常友好,因爲計算機只懂二進制,那麼收到報文後,無需再將明文的報文轉成二進制,而是直接解析二進制報文,這 增加了數據傳輸的效率

3. 數據流

HTTP/2的數據包不是按順序發送的,同一個連接裏面連續的數據包,可能屬於不同的迴應。因此,必須要對數據包做標記,指出它屬於哪個迴應。

每個請求或迴應的所有數據包,稱爲一個數據流(Stream)。

每個數據流都標記着一個獨一無二的編號,其中規定客戶端發出的數據流編號爲奇數, 服務器發出的數據流編號爲偶數

客戶端還可以 指定數據流的優先級 。優先級高的請求,服務器就先響應該請求。

HTT/1 ~ HTTP/2

4. 多路複用

HTTP/2 是可以在 一個連接中併發多個請求或迴應,而不用按照順序一一對應

移除了 HTTP/1.1 中的串行請求,不需要排隊等待,也就不會再出現「隊頭阻塞」問題, 降低了延遲,大幅度提高了連接的利用率

舉例來說,在一個 TCP 連接裏,服務器收到了客戶端 A 和 B 的兩個請求,如果發現 A 處理過程非常耗時,於是就迴應 A 請求已經處理好的部分,接着迴應 B 請求,完成後,再回應 A 請求剩下的部分。

多路複用

5. 服務器推送

HTTP/2 還在一定程度上改善了傳統的「請求 - 應答」工作模式,服務不再是被動地響應,也可以 主動 向客戶端發送消息。

舉例來說,在瀏覽器剛請求 HTML 的時候,就提前把可能會用到的 JS、CSS 文件等靜態資源主動發給客戶端, 減少延時的等待 ,也就是服務器推送(Server Push,也叫 Cache Push)。

HTTP/3 相比 HTTP/2 性能上的改進

HTTP/2 主要的問題在於:

    多個 HTTP 請求在複用一個 TCP 連接,下層的 TCP 協議是不知道有多少個 HTTP 請求的。

所以一旦發生了丟包現象,就會觸發 TCP 的重傳機制,這樣在一個 TCP 連接中的 所有的 HTTP 請求都必須等待這個丟了的包被重傳回來

  • HTTP/1.1 中的管道( pipeline)傳輸中如果有一個請求阻塞了,那麼隊列後請求也統統被阻塞住了.
  • HTTP/2 多請求複用一個TCP連接,一旦發生丟包,就會阻塞住所有的 HTTP 請求。

這都是基於 TCP 傳輸層的問題,所以 HTTP/3 把 HTTP 下層的 TCP 協議改成了 UDP!

HTTP/1 ~ HTTP/3

UDP 發生是不管順序,也不管丟包的,所以不會出現 HTTP/1.1 的隊頭阻塞 和 HTTP/2 的一個丟包全部重傳問題。

大家都知道 UDP 是不可靠傳輸的,但基於 UDP 的 QUIC 協議 可以實現類似 TCP 的可靠性傳輸。

  • QUIC 有自己的一套機制可以保證傳輸的可靠性的。當某個流發生丟包時,只會阻塞這個流, 其他流不會受到影響

  • TL3 升級成了最新的 3 版本,頭部壓縮算法也升級成了 QPack。

  • HTTPS 要建立一個連接,要花費 6 次交互,先是建立三次握手,然後是 TLS/1.3 的三次握手。QUIC 直接把以往的 TCP 和 TLS/1.3 的 6 次交互 合併成了 3 次,減少了交互次數

TCP HTTPS(TLS/1.3) 和 QUIC HTTPS
所以, QUIC 是一個在 UDP 之上的 TCP + TLS + HTTP/2 的多路複用的協議。

QUIC 是新協議,對於很多網絡設備,根本不知道什麼是 QUIC,只會當做 UDP,這樣會出現新的問題。所以 HTTP/3 現在普及的進度非常的緩慢,不知道未來 UDP 是否能夠逆襲 TCP。


參考文獻:

[1] 上野 宣.圖解HTTP.人民郵電出版社.

[2] 羅劍鋒.透視HTTP協議.極客時間.

[3] 陳皓.HTTP的前世今.酷殼CoolShell.

[4] 阮一峯.HTTP 協議入門.阮一峯的網絡日誌.


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