自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

前后端開發(fā)必會的 HTTP 協(xié)議“十全大補(bǔ)丸”

網(wǎng)絡(luò) 網(wǎng)絡(luò)管理
HTTP 協(xié)議是干啥的呢?答案是用于客戶端與服務(wù)器端之間的通信。我們?nèi)粘I暇W(wǎng)過程中最常見的就是 HTTP 協(xié)議了,瀏覽器是最常見的 HTTP 客戶端。

HTTP 協(xié)議全稱為 HyperText Transfer Protocol,即超文本傳輸協(xié)議。

  • 超文本:指文字、圖片、音頻、視頻、文件等的混合體,比如最常見的 HTML。
  • 傳輸:指數(shù)據(jù)從一方轉(zhuǎn)移到另一方,二者之間可能相距數(shù)千里。
  • 協(xié)議:指通信雙方所做的一些約定,比如怎么開始通信、信息的格式與順序、怎么結(jié)束通信等。

HTTP 協(xié)議是干啥的呢?答案是用于客戶端與服務(wù)器端之間的通信。我們?nèi)粘I暇W(wǎng)過程中最常見的就是 HTTP 協(xié)議了,瀏覽器是最常見的 HTTP 客戶端。

圖片

比如我們使用瀏覽器訪問淘寶時,瀏覽器就會發(fā)送一個遵循 HTTP 協(xié)議的請求報文到淘寶服務(wù)器,告訴淘寶服務(wù)器自己想要獲取淘寶首頁信息。

淘寶服務(wù)器收到此報文后,則會發(fā)送一個同樣遵循 HTTP 協(xié)議的響應(yīng)報文到瀏覽器,此響應(yīng)報文中包含淘寶首頁的內(nèi)容。

瀏覽器收到響應(yīng)報文后解析其內(nèi)容并展示在界面上。

圖片

1. HTTP 請求

客戶端向服務(wù)器端發(fā)送的信息稱為請求報文,一般結(jié)構(gòu)如下:

圖片

(1)請求行

請求行用于說明要做些什么,包含三部分內(nèi)容,中間用空格分割。

  • 方法,指定要對請求資源做什么樣的操作(比如查詢、修改等)。常見的方法有:GET、POST、PUT、DELETE、HEAD 等。在前后端分離開發(fā)中,經(jīng)常會遵循 RESTful 設(shè)計風(fēng)格,其使用 POST、DELETE、PUT、GET 分別表示對數(shù)據(jù)的增、刪、改、查。
  • 資源路徑,指定所要請求資源在服務(wù)器中的位置。比如 /index.html,表示訪問服務(wù)器根目錄下名字為 index 的 html 文件。
  • HTTP 版本,指定所使用的 HTTP 版本。目前使用最多的版本為 HTTP/1.1。

舉個栗子:

圖片

面試中常見的一個問題: GET 和 POST 的區(qū)別是什么?,在這里做一下解答。

  • 首先,一般 GET 請求參數(shù)存放在 URL 中,而 POST 請求參數(shù)存儲在請求體中。因為參數(shù)放在 URL 中可以直接被看到,則 GET 請求相對 POST 請求更不安全。但并不是說 POST 請求安全,因為參數(shù)放在請求體中,如果不采取加密手段的話,技術(shù)人員抓包就能看到明文。同時各個瀏覽器對 URL 長度做了限制,比如 IE 瀏覽器限制 URL 的長度最大為 2KB,這就使得了 GET 請求傳輸?shù)臄?shù)據(jù)長度有了限制,而 POST 請求傳輸數(shù)據(jù)長度無限制。
  • 其次,一般 GET 請求用于獲取數(shù)據(jù),POST 請求用于新增數(shù)據(jù)。這里需要提一下冪等性的概念。冪等性是指對于同一個系統(tǒng),在同樣條件下,一次請求和重復(fù)多次請求對資源的影響是一致的,不會因為多次請求而產(chǎn)生了副作用。GET 請求用于獲取資源,不會對系統(tǒng)資源進(jìn)行改變,因此是冪等的。POST 用于新增資源,這意味著多次請求將創(chuàng)建多個資源,因此不是冪等的。基于這個特點,GET 請求可被緩存、可保留在瀏覽器歷史記錄中、瀏覽器回退不會產(chǎn)生副作用,而 POST 請求反之。
  • 最后,GET 和 POST 在本質(zhì)上并無區(qū)別。HTTP 的底層是 TCP,所以無論是 GET 還是 POST 底層都是通過 TCP 進(jìn)行連接通信。我們可以給 GET 加請求體,給 POST 帶上 URL 參數(shù),可以用 GET 請求新增數(shù)據(jù),POST 請求查詢數(shù)據(jù),實際上也是完全可行的。

圖片

(2)請求頭

請求頭用于向服務(wù)器傳遞一些額外的重要信息,比如所能接收的語言等。

請求頭由字段名和字段值構(gòu)成,二者之間用冒號進(jìn)行分隔。常見的一些請求頭有:

請求頭

含義

Host

接收請求的域名

User-Agent

客戶端軟件的名稱和版本號等相關(guān)信息

Connection

設(shè)置發(fā)送響應(yīng)之后 TCP 連接是否繼續(xù)保持的通信選項

Cache-Control

控制緩存的相關(guān)信息

Referer

記錄請求的來源(當(dāng)通過點擊超級鏈接進(jìn)入下一個頁面時,會記錄上一個頁面的 URI)

Accept

客戶端可支持的數(shù)據(jù)類型, 以 MIME 類型來表示

Accept-Encoding

客戶端可支持的編碼格式

Accept-Language

客戶端可支持的語言

If-Modified-Since

用于判斷資源的緩存是否有效(客戶端通知服務(wù)器,本地緩存的最后變更時間)

If-None-Match

用于判斷資源的緩存是否有效

Range

用于斷點續(xù)傳,指定第一個字節(jié)的位置和最后一個字節(jié)的位置。

Cookie

表示請求者的身份,用于保存狀態(tài)信息

(3)請求空行

請求空行用于表明請求頭已經(jīng)結(jié)束。

(4)請求體

請求體用于傳送客戶端要發(fā)給服務(wù)器的數(shù)據(jù),比如請求參數(shù),通常出現(xiàn)在 POST 請求方法中,而 GET 方法無請求體,它的請求參數(shù)直接會顯示在網(wǎng)址上面。

請求行和請求頭的數(shù)據(jù)都是文本形式且格式化的,而請求體不同,其可以包含任意的二進(jìn)制數(shù)據(jù),比如文本、圖片、視頻等等。

2. HTTP 響應(yīng)

服務(wù)器向客戶端發(fā)送的信息稱為響應(yīng)報文,響應(yīng)報文的結(jié)構(gòu)一般如下:

圖片

(1)響應(yīng)行

響應(yīng)行用于說明對請求的處理情況,包含三部分內(nèi)容,中間用空格分割。

  • HTTP 版本,指定所使用的 HTTP 版本。比如 HTTP/1.1 表示使用的 HTTP 版本是 1.1。
  • 狀態(tài)碼,以三位數(shù)字形式描述服務(wù)器對請求的處理結(jié)果。比如 200 表示成功。
  • 消息短語,以文本形式描述服務(wù)器對請求的處理結(jié)果。比如 OK 表示成功。

舉個栗子:

圖片

面試中常見的一個問題: HTTP 有哪些常見狀態(tài)碼?,在這里做一下解答。

圖片

  • 200 OK:表示請求被正常處理,這是最常見的狀態(tài)碼。
  • 204 No Content:表示請求被正常處理,但在返回的響應(yīng)報文中不含響應(yīng)體內(nèi)容。
  • 301 Moved Permanently? :永久重定向,表示請求的資源已經(jīng)被永久轉(zhuǎn)移了,新的 URL 定義在響應(yīng)報文的 Location 字段中,瀏覽器將自動獲取新的 URL 發(fā)出新的請求。場景:比如建設(shè)一個網(wǎng)站后,將網(wǎng)站的 url 變換了,重新申請一個域名,但是希望之前 url 仍然可以訪問到,就可以做一個重定向到新的 url 下面。比如京東最早網(wǎng)址 http://www.360buy.com 重定向到 http://www.jd.com。
  • 302 Found? :臨時重定向(即以后還可能有變化),表示請求的資源已被臨時分配了新的 URL,新的 URL 會在響應(yīng)報文中的 Location 字段中返回,瀏覽器將會自動使用新的 URL 發(fā)出新的請求。比如用戶在未登錄時訪問個人中心頁面,這時可以臨時重定向到登錄的 url;或者協(xié)議發(fā)生變化,比如京東 http://www.jd.com 重定向到 https://www.jd.com;再比如,今天夜里網(wǎng)站后臺要系統(tǒng)維護(hù),服務(wù)暫時不可用,這就屬于『臨時』的,可以配置成 302 跳轉(zhuǎn),把流量臨時切換到一個靜態(tài)通知頁面,瀏覽器看到這個 302 就知道這只是暫時的情況,不會做緩存優(yōu)化,第二天還會訪問原來的地址。
  • 304 Not Modified:代表上次的文檔已經(jīng)被緩存了,還可以繼續(xù)使用,即訪問緩存。
  • 400 Bad Request:一個通用差錯狀態(tài)碼,表示請求報文中存在語法錯誤,客戶端發(fā)生的錯誤。
  • 401 Unauthorized :用戶未認(rèn)證。
  • 403 Forbidden:表示服務(wù)器雖然收到了請求,但是拒絕提供服務(wù),常見的原因是為沒有訪問權(quán)限(即用戶未授權(quán))。
  • 404 Not Found :表示請求資源不存在。
  • 500 Internal Server Error:表示服務(wù)器出現(xiàn)錯誤,可能是出現(xiàn)了一些 Bug 或故障。
  • 502 Bad Gateway:通常是服務(wù)器作為網(wǎng)關(guān)或代理時返回的錯誤碼,表示服務(wù)器自身工作正常,訪問后端服務(wù)器發(fā)生了錯誤(可能后端服務(wù)器宕機(jī)了)。
  • 503 Service Unavailable:表示服務(wù)器暫時處于超負(fù)載或者正在進(jìn)行停機(jī)維護(hù),暫時無法處理請求,可以稍后再試。Web 服務(wù)器如果限流,就可以給超載的流量直接響應(yīng) 503 狀態(tài)碼。

(2)響應(yīng)頭

響應(yīng)頭用于向客戶端傳遞一些額外的重要信息,比如響應(yīng)內(nèi)容的長度等。

響應(yīng)頭由字段名和字段值構(gòu)成,二者之間用冒號進(jìn)行分隔。常見的一些響應(yīng)頭有:

響應(yīng)頭

含義

Date

日期時間信息,表示服務(wù)器產(chǎn)生并發(fā)送響應(yīng)報文的日期和時間。

Server

表示HTTP服務(wù)器應(yīng)用程序的信息,類似于請求報文中的 User-Agent

Location

此字段會配合重定向使用,用于提供重定向后新的 URI。

Connection

設(shè)置發(fā)送響應(yīng)之后 TCP 連接是否繼續(xù)保持的通信選項

Cache-Control

控制緩存的相關(guān)信息

Content-Type

服務(wù)器返回的響應(yīng)類型

Content-length

服務(wù)器返回的響應(yīng)長度

Content-Encoding

服務(wù)器返回的響應(yīng)編碼

Content-Language

服務(wù)器返回的響應(yīng)語言

Last-Modified

指定響應(yīng)內(nèi)容最后的修改時間

Expires

表示資源失效的時間,瀏覽器會在指定過期時間內(nèi)使用本地緩存

Etag

用于協(xié)商緩存,返回一個摘要值

Accept-Ranges

用于斷點續(xù)傳,指定服務(wù)器所支持的內(nèi)容范圍

Set-Cookie

設(shè)置狀態(tài)信息

(3)響應(yīng)空行

響應(yīng)空行用于表明響應(yīng)頭已經(jīng)結(jié)束。

(4)響應(yīng)體

響應(yīng)體用于傳送服務(wù)器要發(fā)給瀏覽器的正文。

同請求報文的請求體一樣,響應(yīng)體可包含任意的二進(jìn)制數(shù)據(jù)。瀏覽器收到響應(yīng)報文后,則會將正文加載到內(nèi)存,然后解析渲染,最后顯示頁面內(nèi)容。

3. HTTP 持久連接

客戶端發(fā)送一系列請求給服務(wù)器,如果服務(wù)器與客戶端對每個請求/響應(yīng)對都經(jīng)過一個單獨(dú)的 TCP 連接發(fā)送,則稱為非持續(xù)連接,也稱為短連接;如果經(jīng)過相同的 TCP 連接發(fā)送,則稱為持續(xù)連接,也稱為長連接。

比如打開一個 Web 頁面時,假設(shè)該頁面含有一個 HTML 基礎(chǔ)文件和 2 張圖片,如果客戶端與服務(wù)器通過同一個 TCP 連接來獲取這 3 個數(shù)據(jù),則為持續(xù)連接,如果通過建立 3 次不同的 TCP 連接,則為非持續(xù)連接。

圖片

非持續(xù)連接的缺點:

  • 每次建立連接需要三次握手過程,導(dǎo)致總的請求響應(yīng)時間變長。當(dāng)然也不是絕對的,如果多個連接可以并行請求,總響應(yīng)時間可能變短,比如 Chrome 瀏覽器為了提升加載速度,可以同時打開 6 個并行連接,但多個并行連接會加重 Web 服務(wù)器負(fù)擔(dān)。
  • 必須為每一個請求的對象建立和維護(hù)一個全新的連接,而每一個連接都需要客戶和服務(wù)器分配 TCP 的緩沖區(qū)和保持 TCP 變量,使得 Web 服務(wù)器存在嚴(yán)重的負(fù)擔(dān),因為一臺 Web 服務(wù)器可能同時服務(wù)于數(shù)以百計不同的客戶的請求。

HTTP(1.1 及之后) 默認(rèn)采用持續(xù)連接方式,但也可配置成非持續(xù)連接方式。在報文中使用 Connection 字段來表示是否使用持久連接。

  • 如果 Connection 字段的值為 keep-alive,則表明此連接為持久連接,HTTP1.1 及以后可默認(rèn)不寫。
  • 如果 Connection 字段的值為 close,則表明要關(guān)閉連接。

注意:持久連接不是永久連接,一般在一個可配置的超時間隔后,如果此連接仍未被使用,HTTP 服務(wù)器就會關(guān)閉該連接。

4. HTTP 緩存

對于一些短時間內(nèi)不會產(chǎn)生變化的資源,客戶端(瀏覽器)可以在一次請求后將服務(wù)器響應(yīng)的資源緩存在本地,之后直接讀取本地的數(shù)據(jù),而不必再重新發(fā)送請求。

我們經(jīng)常會接觸到『緩存』這一概念,比如由于內(nèi)存和 CPU 之間速度差距較大,為了進(jìn)一步提升電腦性能,于是設(shè)計了 L1 緩存、L2 緩存等,讓 CPU 先從緩存中取數(shù)據(jù),如果取不到,再去內(nèi)存取。

圖片

又比如在后端開發(fā)中,由于數(shù)據(jù)庫一般存儲在硬盤上,讀取速度較慢,于是可能會采用 Redis 等內(nèi)存數(shù)據(jù)庫作為緩存,先去 Redis 中取數(shù)據(jù),如果取不到,再去數(shù)據(jù)庫中取。

再比如在操作系統(tǒng)中,由于頁表進(jìn)行地址轉(zhuǎn)換的速度較慢,于是有了 TLB 快表,當(dāng)需要進(jìn)行邏輯地址到物理地址的轉(zhuǎn)換時,先去查詢速度更快的 TLB 快表,如果查不到,再去查詢頁表,此時 TLB 快表就是一種緩存。

緩存的主要目的在于提升查詢速度,一般邏輯如圖所示。

圖片

同樣,在 HTTP 設(shè)計中也有緩存的概念,主要是為了加快響應(yīng)速度,HTTP 緩存的實現(xiàn)依賴于請求報文和響應(yīng)報文中的一些字段,分為強(qiáng)緩存和協(xié)商緩存。

(1)強(qiáng)緩存

強(qiáng)緩存指的是在緩存數(shù)據(jù)未失效的情況下,那么就會直接使用瀏覽器的緩存數(shù)據(jù),不會再向服務(wù)器發(fā)送任何請求,邏輯類似于前面舉的 L1 緩存、Redis、TLB 快表。

具體實現(xiàn)主要是通過 Cache-Control?字段和 Expires字段。

Cache-Control 是一個相對時間(即多長時間后過期,http1.1 規(guī)范),Expires 是一個絕對時間(即在某個時間點過期,http1.0 規(guī)范),如果兩個字段同時存在,Cache-Control 的優(yōu)先級更高。

圖片

由于服務(wù)器端時間和客戶端時間可能不同步,存在偏差,這也就是導(dǎo)致了使用 Expires 可能會存在時間誤差,因此一般更推薦使用 Cache-Control 來實現(xiàn)強(qiáng)緩存。

以 Cache-Control 為例,強(qiáng)緩存的具體的實現(xiàn)流程如下:

圖片

  1. 當(dāng)瀏覽器第一次請求訪問服務(wù)器資源時,服務(wù)器會在響應(yīng)頭中加上 Cache-Control。Cache-Control 中可以設(shè)置以下內(nèi)容。

max-age=秒?,表示緩存將于指定毫秒值后過期。比如:cache-control: max-age=31536000,表示緩存將于 365 天后過期。

no-store,表示不允許緩存(包括強(qiáng)緩存和協(xié)商緩存)。

no-cache?,表示不使用強(qiáng)緩存,而是使用協(xié)商緩存,即使用之前必須要先去服務(wù)器端驗證是否失效,如果沒失效,則再使用緩存,如果失效了,則返回最新數(shù)據(jù)。等價于max-age=0, must-revalidate。

must-revalidate?,表示允許緩存,并且如果緩存不過期的話,先使用緩存,如果緩存過期的話,再去服務(wù)器端進(jìn)行驗證緩存是否還有效。這里很多小伙伴可能會有疑問,即使沒有加上 must-revalidate,有了 max-age 后,緩存過期了不也會去服務(wù)器驗證嗎,加不加 must-revalidate 有什么區(qū)別呢?在 HTTP 協(xié)議規(guī)范中,允許客戶端在某些特殊情況下直接使用過期緩存,比如校驗請求錯誤時(如無法再次連通服務(wù)器),而加上了 must-revalidate 后,在校驗請求錯誤時,會返回 504 錯誤碼,而不是使用過期緩存。

  1. 瀏覽器再次請求訪問服務(wù)器中的該資源時,根據(jù)請求資源的時間與 Cache-Control 中設(shè)置的過期時間大小,計算出該資源是否過期,
  2. 如果沒有過期(且 Cache-Control 沒有設(shè)置 no-cache 屬性和 no-store 屬性),則使用該緩存,結(jié)束;

  3. 否則重新請求服務(wù)器;

(2)協(xié)商緩存

協(xié)商緩存指的是當(dāng)?shù)谝淮握埱蠛?,服?wù)器響應(yīng)頭 Cache-Control 字段屬性設(shè)置為 no-cache 或者緩存時間過期了,那么瀏覽器再次請求時就會與服務(wù)器進(jìn)行協(xié)商,判斷緩存資源是否有效,即資源是否進(jìn)行了修改更新。

  • 如果資源沒有更新,那么服務(wù)器返回 304 狀態(tài)碼,表明緩存仍然可用,而不需要再次發(fā)送資源,減少了服務(wù)器的數(shù)據(jù)傳輸壓力,并更新緩存時間。
  • 如果數(shù)據(jù)有更新,服務(wù)器返回 200 狀態(tài)碼,新資源存放在請求體中。

圖片

協(xié)商緩存可以基于以下兩種方式來實現(xiàn):

第一種(HTTP/1.0 規(guī)范):請求頭部中的 If-Modified-Since? 字段與響應(yīng)頭部中的 Last-Modified 字段:

圖片

  • Last-Modified:標(biāo)示這個響應(yīng)資源的最后修改時間。第一次請求資源后,服務(wù)器將在響應(yīng)頭中帶上此信息。
  • If-Modified-Since:當(dāng)資源過期了,瀏覽器再次發(fā)起請求的時候帶上 Last-Modified 的時間(放在請求頭 If-Modified-Since 中),服務(wù)器將此時間與被請求資源的最后修改時間進(jìn)行對比,

如果最后修改時間較大,說明資源有被修改過,則返回最新資源和 200 狀態(tài)碼;

否則說明資源無新修改,返回 304 狀態(tài)碼。

  • 此種方式存在以下問題:
  • 基于時間實現(xiàn),可能會由于時間誤差而出現(xiàn)不可靠問題,并且只能精確到秒級,在同一秒內(nèi),Last-Modified 無感知。

  • 如果某些文件被修改了,但是內(nèi)容并沒有任何變化(比如只是修改時間發(fā)生了變化),而 Last-Modified 卻改變了,導(dǎo)致文件沒法使用緩存。

第二種(HTTP/1.1 規(guī)范):請求頭部中的 If-None-Match? 字段與響應(yīng)頭部中的 ETag 字段:

圖片

  • Etag:唯一標(biāo)識響應(yīng)資源,是一個 hash 值;第一次請求資源后,服務(wù)器將在響應(yīng)頭中帶上此信息。
  • If-None-Match:當(dāng)資源過期了,瀏覽器再次向服務(wù)器發(fā)起請求時,會將請求頭 If-None-Match 值設(shè)置為 Etag 中的值。服務(wù)器將此值與資源的 hash 值進(jìn)行比對,

如果二者相等,則資源沒有變化,則返回 304 狀態(tài)碼。

如果資源變化了,則返回新資源和 200 狀態(tài)碼。

  • 此種方式存在的問題在于計算 Etag 會消耗系統(tǒng)性能,但可以解決第一種方式所存在的問題,推薦使用。

注意 :

  • 如果 HTTP 響應(yīng)頭部同時有 Etag 和 Last-Modified 字段的時候,Etag 的優(yōu)先級更高,也就是先會判斷 Etag 是否變化了,如果 Etag 沒有變化,然后再看 Last-Modified。
  • Ctrl + F5 強(qiáng)制刷新,會直接向服務(wù)器提取數(shù)據(jù)。
  • 按 F5 刷新或瀏覽器的刷新按鈕,默認(rèn)加上 Cache-Control:max-age=0,即會走協(xié)商緩存。

5. Cookie

HTTP 是一種無狀態(tài)協(xié)議,即其本身不會記憶請求和響應(yīng)之間的通信狀態(tài),那么 Web 服務(wù)器就無法判斷此請求到底來自于哪個用戶,HTTP 協(xié)議中并不會保存關(guān)于用戶的任何信息。這樣設(shè)計的好處是不需要額外資源保存用戶狀態(tài)信息,減少了服務(wù)器的 CPU 及內(nèi)存資源的消耗。

但是隨著 Web 的發(fā)展,很多業(yè)務(wù)需要保存用戶狀態(tài)。

  • 比如電商網(wǎng)站需要在用戶跳轉(zhuǎn)到其他商品頁面時,仍然可以保存用戶的登錄狀態(tài)。不然用戶每訪問一次網(wǎng)站都要重新登錄一下,過于繁瑣,體驗效果就很差。
  • 比如短視頻網(wǎng)站希望記錄用戶以前看過的視頻,以便之后向其精準(zhǔn)化推薦感興趣的視頻。

為了實現(xiàn)保持狀態(tài)的功能,這就出現(xiàn)了 Cookie。Cookie (服務(wù)器給的憑證)類似于我們逛商場時的會員卡(商家給的憑證),記錄著我們的身份信息,只要出示了會員卡,商場工作人員就能確定我們的身份。同樣的,只要給服務(wù)器發(fā)送報文時帶上了 Cookie,他就知道我們是誰了。

圖片

Cookie 中可以包含任意信息,最常見的是包含一個服務(wù)器為了進(jìn)行跟蹤而產(chǎn)生的獨(dú)特的識別碼。

舉個栗子:

張三在發(fā)出第一次請求后,服務(wù)器將其狀態(tài)信息記錄下來,比如他的名字、年齡、地址、購物歷史等,并通過響應(yīng)頭 Set-Cookie?字段,給予其一個 id=12345 的獨(dú)特識別碼作為 Cookie,那么其再次向服務(wù)器發(fā)出請求時,瀏覽器會自動在請求報文中的 Cookie 字段中帶上 id=12345,服務(wù)器就可以通過這個查詢到張三的具體信息,從而實現(xiàn)了保持狀態(tài)的功能。

圖片

Cookie 屬性:

  • max-age:過期時間有多長(絕對時間,單位:秒)。

負(fù)數(shù),表示瀏覽器關(guān)閉即失效。默認(rèn)即為 -1。

正數(shù):失效時刻= 創(chuàng)建時刻+ max-age。

0:表示 Cookie 立即刪除,即 Cookie 直接過期(從而實現(xiàn)使 cookie 失效)。

  • expires:過期時間(相對時間)。
  • secure:表示這個 Cookie 只會在 https 的時候才會發(fā)送。
  • HttpOnly:設(shè)置后無法通過使用 JavaScript 腳本訪問,可以保障安全,防止攻擊者盜用用戶 Cookie。
  • domain:表示該 Cookie 對于哪個域是有效的。(Cookie 默認(rèn)是不能直接跨域訪問的,但是二級域名是可以共享 cookie 的)

Cookie 的缺點是如果傳遞的狀態(tài)信息較多,使得包過大,將會降低網(wǎng)絡(luò)傳輸效率。

一般瀏覽器限制 Cookie 大小為 4KB。

6. HTTP 版本

隨著互聯(lián)網(wǎng)的發(fā)展,HTTP 也在不斷升級打怪,下面分別介紹一下 HTTP/1.1、HTTP/2 以及 HTTP/3 在前一版本基礎(chǔ)上的改進(jìn)之處。

(1)HTTP/1.1 相比 HTTP/1.0 性能上的改進(jìn)

HTTP/1.1 是目前最常見的 HTTP 版本,其相對于 HTTP/1.0 有以下改進(jìn)。

① 持久連接

這個在前文中已經(jīng)提到過,HTTP/1.0 中一個 TCP 連接只能發(fā)送一個請求和響應(yīng),而 HTTP/1.1 進(jìn)行了優(yōu)化,同一個 TCP 連接可以發(fā)送多次 HTTP 請求,減少了建立和關(guān)閉連接的性能開銷。

圖片

Web 服務(wù)軟件一般都會提供 keepalive_timeout 參數(shù),用來指定 HTTP 持久連接的超時時間。比如設(shè)置了 HTTP 持久連接的超時時間是 60 秒,Web 服務(wù)軟件就會啟動一個定時器,如果完成某個 HTTP 請求后,在 60 秒內(nèi)都沒有再發(fā)起新的請求,就會觸發(fā)回調(diào)函數(shù)來釋放該連接。

② 管道機(jī)制

持久連接雖然可以多個請求復(fù)用同一個連接,但是每次都需要等到上一個請求響應(yīng)完成后,才能發(fā)送下一個請求。

管道機(jī)制中,只要第一個請求發(fā)出去了,不必等其回來,就可以發(fā)第二個請求出去,即相當(dāng)于同時發(fā)出多個請求,因而可以減少整體的響應(yīng)時間。

圖片

雖然客戶端可以同時發(fā)出多個 HTTP 請求,不用?個個等待響應(yīng),但是服務(wù)器必須按照接收請求的順序依次發(fā)送對這些管道化請求的響應(yīng),以保證客戶端能夠區(qū)分出每次請求的響應(yīng)內(nèi)容。這存在下面問題:

如果服務(wù)端在處理一個請求時耗時比較長,那么后續(xù)請求的處理都會被阻塞住,會導(dǎo)致客戶端遲遲收不到數(shù)據(jù),這稱為「隊頭堵塞」。

實際上,雖然管道機(jī)制的想法很好,但實現(xiàn)卻非常困難,因而很多瀏覽器根本不支持它。一般為了提升性能,采用并行多個 TCP 連接的形式來實現(xiàn)請求的同時發(fā)送。

圖片

③ 緩存控制

前文已經(jīng)提到過,HTTP/1.1 在 HTTP/1.0 基礎(chǔ)之上,增加了一些請求響應(yīng)頭,以更好的實現(xiàn)對緩存的控制。比如

  • 新增 Cache-Control 代替原先的 Expires;
  • 新增 If-None-Match 和 Etag 代替原先的  If-Modified-Since和 Last-Modified 。

④ 斷點續(xù)傳

利? HTTP 消息頭使?分塊傳輸編碼,將實體主體分塊傳輸。

(2)HTTP/2 相比 HTTP/1.1 性能上的改進(jìn)

HTTP/2 協(xié)議本身是基于 HTTPS 的,因此更加安全,其相對于 HTTP/1.1 有以下改進(jìn)。

① 頭部壓縮

HTTP/1.1 中的請求頭攜帶大量信息,而且每次都要重復(fù)發(fā)送,即使是同樣的內(nèi)容,每次請求都需要附帶,這會造成性能的損耗。HTTP/2 進(jìn)行了優(yōu)化,引入了頭信息壓縮機(jī)制。

客戶端和服務(wù)器同時維護(hù)一張頭信息表,高頻出現(xiàn)的字段會存入這個表,生成一個索引號。發(fā)送報文時直接使用索引號替代字段。另外,索引表中不存在的字段使用哈夫曼編碼壓縮。

同時,多個請求中,如果請求頭相同,則后續(xù)請求只需要發(fā)送差異的部分,重復(fù)的部分無需再發(fā)送。

圖片

② 二進(jìn)制幀

HTTP/1.1 的報文為純文本格式,而 HTTP/2 的報文全面采用二進(jìn)制格式,并將原始的報文拆分為頭信息幀(Headers Frame)和數(shù)據(jù)幀(Data Frame)。采用二進(jìn)制格式有利于提升數(shù)據(jù)傳輸效率。

③ 多路復(fù)用

在 HTTP/2 中定義了流(Stream)的概念,它是二進(jìn)制幀的雙向傳輸序列,一個數(shù)據(jù)流對應(yīng)著一個完整的請求-響應(yīng)過程,在同一個請求響應(yīng)過程中,往返的幀會分配一個唯一的流編號(Stream ID)。

在流的支持下,HTTP/2 可以在一個 TCP 連接中傳輸多個請求或響應(yīng),而不用按照順序一一對應(yīng)(即實現(xiàn)多路復(fù)用),因為它們屬于不同的流,所發(fā)送的幀頭部都會攜帶 Stream ID,可以通過此 Stream ID 有效區(qū)分不同的請求-響應(yīng)。

圖片

因而 HTTP/2 解決了 HTTP/1.1 的『隊頭阻塞』問題,多個請求 - 響應(yīng)之間沒有了順序關(guān)系,不需要排隊等待,降低了延遲,大幅度提高了連接的利用率。

舉個栗子:

在一個 TCP 連接里面,服務(wù)器同時收到了 A 請求和 B 請求,于是先回應(yīng) A 請求,結(jié)果發(fā)現(xiàn)處理過程非常耗時,于是就發(fā)送 A 請求已經(jīng)處理好的部分,接著回應(yīng) B 請求,完成后,再發(fā)送 A 請求剩下的部分。

④ 服務(wù)端推送

在 HTTP/1.1 中,只能客戶端發(fā)起請求,服務(wù)器對請求進(jìn)行響應(yīng)。

而在 HTTP/2  中,服務(wù)端可以主動給客戶端推送必要的資源,以減少請求延遲時間。

比如當(dāng)客戶端向服務(wù)器請求一個 HTML? 文件后,服務(wù)器除了將此 HTML? 文件響應(yīng)給客戶端外,還可以提前主動將此 HTML? 中所依賴的 JS? 和 CSS? 文件推送給客戶端,這樣客戶端在解析 HTML? 時,無需耗費(fèi)額外的請求去得到相應(yīng)的 JS? 和 CSS 文件。

圖片

(3)HTTP/3 相比 HTTP/2 性能上的改進(jìn)

Google 公司為了解決 HTTP/2 存在的一些問題,提出了 QUIC 協(xié)議,而 HTTP-over-QUIC 就是 HTTP/3,其相對于 HTTP/2 有以下改進(jìn)。

① 無隊頭阻塞

前面提到,HTTP/2 通過多路復(fù)用解決了 HTTP1.1 的『隊頭阻塞』問題,但其只是解決了 HTTP 這一層面的『隊頭阻塞』問題,底層仍然采用的 TCP 連接,HTTP/2 并沒有解決 TCP 的『隊頭阻塞』問題。

TCP 是可靠的、面向字節(jié)流的協(xié)議。HTTP/2 的多個請求雖然可以跑在同一個 TCP 連接中,但如果出現(xiàn)丟包現(xiàn)象,TCP 就需要進(jìn)行重傳,這可能就會導(dǎo)致整個 TCP 連接上的所有流阻塞,直到丟的包重傳成功,這就是 TCP 的『隊頭阻塞』問題。

為了解決此問題,HTTP/3 底層不再使用 TCP,而是采用 UDP!而 UDP 是無連接的,多個流互相獨(dú)立,之間不再有依賴,因而即使某個流發(fā)生了丟包,只會對該流產(chǎn)生影響,并不會使得其他流阻塞!

這時候有的小伙伴可能會問了,HTTP/3 底層不采用 TCP,那怎么保證可靠傳輸呢?答案就是 HTTP/3 在應(yīng)用層自己重新實現(xiàn)了可靠性機(jī)制。也就是說,HTTP/3 將原先 TCP 協(xié)議提供的部分功能上移至 QUIC,而且進(jìn)行了改進(jìn)。

圖片

② 優(yōu)化重傳機(jī)制

TCP 采用序號+確認(rèn)號+超時重傳機(jī)制來保證消息的可靠性,即如果某條消息超過一定時間還沒有得到確認(rèn),則重新發(fā)送此消息。

由于網(wǎng)絡(luò)擁堵情況不斷變化,因而消息的超時時間并不是固定的,而是通過不斷采樣消息的往返時間不斷調(diào)整的,但 TCP 超時采樣存在不準(zhǔn)確的問題。

舉個栗子:

客戶端發(fā)送一個序號為 N 的包,然后超時了(可能丟了,也可能網(wǎng)絡(luò)堵塞了),于是重新發(fā)送一個序號為 N 的包,之后服務(wù)器收到后返回一個確認(rèn)號 ACK 為 N+1 的包。但此時客戶端并無法判斷這個確定包是對原始報文的確認(rèn)還是重傳報文的確認(rèn),那么此時往返時間應(yīng)該如何計算呢?

  • 如果認(rèn)為確認(rèn)包是對原始報文的確認(rèn),則可能把時間算長了;
  • 如果認(rèn)為確認(rèn)包是對重傳報文的確認(rèn),則可能包時間算長了。

因而 TCP 的重傳超時時間計算不準(zhǔn)確,如果計算偏大,則效率慢,很久才會重傳,而如果計算偏小,則可能確認(rèn)報文已經(jīng)在路上了,但卻重傳了!

圖片

QUIC 是如何解決此問題呢?其定義了一個遞增的序列號(不再叫 Seq,而是 Packet Number),每個序列號的包只發(fā)送一次,即使重傳相同的包,其序列號也不一樣。

舉個栗子:

客戶端發(fā)送一個序號為 N 的包,然后超時了,于是重新發(fā)送一個相同的包,但序號不再是 N,而是 N+1;那么如果返回的確認(rèn)包 ACK 為 N+1,就是對原始報文的響應(yīng),如果 ACK 為 N+2,就是對重傳報文的響應(yīng),因而采樣時間計算相對更加準(zhǔn)確!

圖片

那此時怎么知道包 N 和包 N+1 是同一個包呢?QUIC 定義了一個 Offset 概念。發(fā)送的數(shù)據(jù)有個偏移量 Offset,可以通過 Offset 知道數(shù)據(jù)目前發(fā)送到了哪里,因而如果某個 Offset 的包沒有收到確認(rèn),就重發(fā)。

③ 連接遷移

眾所周知,一條 TCP 連接是由四元組標(biāo)識的,分別是源 IP、源端口、目的 IP、目的端口。一旦其中一個元素發(fā)生了變化,就需要斷開重連。

當(dāng)手機(jī)信號不穩(wěn)定或者在 WIFI 與移動網(wǎng)絡(luò)切換時,都將會導(dǎo)致重連,而重連就意味著需要重新進(jìn)行三次握手,將產(chǎn)生一定的時延,用戶感到卡頓,體驗不友好。

而 QUIC 不采用四元組的方式標(biāo)識連接,而是以一個 64 位的隨機(jī)數(shù)作為 ID 來標(biāo)識,通過此連接 ID 標(biāo)記通信的兩端,之后即使網(wǎng)絡(luò)發(fā)生變化,IP 或端口變了,但只要 ID 不變,則無需重連,只需要復(fù)用原先連接即可,時延低,減少了用戶的卡頓感,實現(xiàn)連接遷移。

圖片

(4)總結(jié)

圖片

本文轉(zhuǎn)載自微信公眾號「 一楓說碼」,作者「一楓說碼」,可以通過以下二維碼關(guān)注。

轉(zhuǎn)載本文請聯(lián)系「 一楓說碼」公眾號。

責(zé)任編輯:武曉燕 來源: 一楓說碼
相關(guān)推薦

2021-10-13 18:52:49

辦公

2022-01-27 15:36:04

Windows 11WindowsWindows 10

2024-11-15 11:11:48

2019-12-16 09:21:14

HTTPAPI認(rèn)證

2012-12-27 15:57:12

2009-07-23 11:40:50

虛擬化IDC機(jī)房

2015-11-16 14:47:49

Windows 10TH2更新

2015-10-20 09:46:33

HTTP網(wǎng)絡(luò)協(xié)議

2019-08-28 20:34:52

5GHTCVR

2014-04-18 10:04:15

NodeJS前后端分離

2015-11-19 13:56:39

開源LinuxLinux安全操作系統(tǒng)安全

2010-10-09 20:36:32

無線路由無線產(chǎn)品斐訊

2019-06-12 19:00:14

前后端分離AppJava

2010-01-05 10:14:19

2009年數(shù)據(jù)中心領(lǐng)域

2023-02-08 16:29:58

前后端開發(fā)

2022-02-28 09:31:02

開發(fā)環(huán)境后端前端

2021-03-03 13:25:35

CookieSessionToken

2018-10-25 10:39:41

新華三

2016-01-14 15:02:42

2023-11-08 18:01:53

硬重置Git命令
點贊
收藏

51CTO技術(shù)棧公眾號