1. 程式人生 > >網路協議之 - HTTP

網路協議之 - HTTP

前言

關於HTTP的知識比較繁雜,也比較零散,於是想要通過這篇文章對常用知識點進行總結,一些知識點描述是從網上搜集而來,如有侵權,可以聯絡我進行修改。

提出問題

  1. Http的報文結構。
  2. Http request的幾種型別。
  3. Http的狀態碼含義。
  4. Http1.1和Http1.0的區別,以及快取原理
  5. Http長連線keep-alive。
  6. Cookie與Session的作用於原理。
  7. 電腦上訪問一個網頁,整個過程是怎麼樣的:DNS、HTTP、TCP、OSPF、IP、ARP。

解答

1. Http的報文結構

http協議的請求報文和響應報文都是由以下4部分組成:

  1. 請求行
  2. 請求頭
  3. 空行 CR + LF,回車 + 換行
  4. 請求體

2. Http request的幾種型別

請求行

Request

格式:【方法 URL HTTP版本】 例如: GET /csrfToken HTTP/1.1

HTTP版本:目前有 HTTP/1.0、HTTP/1.1、HTTP/2.0 版本,其中 HTTP1.1 版本使用較廣泛

方法 說明 支援HTTP協議版本
GET 獲取資源 1.0 、1.1
POST 傳輸實體主體 1.0、1.1
PUT 傳輸檔案 1.0、1.1
HEAD 獲得報文首部 1.0、1.1
DELETE 刪除資源 1.0、1.1
OPTIONS 詢問支援的方法 1.1
TRACE 追蹤路徑 1.1
CONNECT 要求用隧道協議連線代理 1.1
LINK 建立和資源之間的聯絡 1.0
UNLINK 斷開連線關係
1.0

Response

格式:【HTTP版本 狀態碼 描述】 例如: HTTP/1.1 200 OKHTTP/1.1 404 NOT FOUND

  類別 原因短語
1xx Informational(資訊性狀態碼) 接收的請求正在處理
2xx Success(成功狀態碼) 請求正常處理完畢
3xx Redirection(重定向狀態碼) 需要進行附加操作以完成請求
4xx Client Error(客戶端錯誤狀態碼) 伺服器無法處理請求
5xx Server Error(伺服器錯誤狀態碼) 伺服器處理請求出錯

3. Http的狀態碼含義

常用狀態碼
  • 200:OK,請求被正常處理
  • 204:No Content,請求被受理但沒有資源可以返回,返回204響應,瀏覽器顯示的頁面不發生更新
  • 206:Partial Content,客戶端進行範圍請求,伺服器成功執行了這部分的GET請求,響應報文中包含由Content-Range指定範圍的實體內容
  • 301:Moved Permanently,永久性重定向,比如訪問http://test.zhixue.com/zbptadmin,伺服器會返回301,response的headers中會包含一個欄位:Location: http://test.zhixue.com/zbptadmin/,瀏覽器會按照這個地址重新請求,並且如果使用者儲存了書籤,瀏覽器會自動按照Location更新書籤
  • 302:Found,臨時性重定向,和301類似,但是瀏覽器不會更新書籤
  • 303:See Other,和302類似,但303明確表示客戶端應該使用GET方法獲取Location資源
  • 備註:當301,302,303響應狀態碼返回時,幾乎所有的瀏覽器都會把POST改成GET,並刪除請求報文內的主體,之後請求會自動再次傳送。301,302標準是禁止將POST方法改成GET方法的,但實際使用時瀏覽器廠商都會這麼做。
  • 304:Not Modified,傳送附帶條件的請求時,(附帶條件的請求是指採用GET方法的請求報文中包含If-Match,If-Modified-Since,If-None-Match,If-Range,If-Unmodified-Since中任一首部),條件不滿足返回304,可直接使用客戶端快取,與重定向無關
  • 307:Temporary Redirect,臨時重定向,與302類似,只是強制要求使用POST方法
  • 400:Bad Request,請求報文中存在語法錯誤,伺服器無法識別
  • 401:Unauthorized,請求需要認證
  • 403:Forbidden,請求對應的資源禁止被訪問
  • 404:Not Found,伺服器無法找到對應資源
  • 500:Internal Server Error,伺服器內部錯誤
  • 503:Service Unavailable,伺服器正忙

常見HTTP首部欄位

通用首部欄位(請求報文與響應報文都會使用的首部欄位)

  • Date:建立報文的時間
  • Connection:連線的管理
  • Cache-Control:快取的控制
  • Transfer-Encoding:報文主題的傳輸編碼方式

請求首部欄位(請求報文會使用的首部欄位)

  • Host:請求資源所在的伺服器
  • Accept:可處理的媒體型別
  • Accept-Charset:可接收的字符集
  • Accept-Encoding:可接收的內容編碼
  • Accept-Language:可接收的自然語言

響應首部欄位(響應報文會使用的首部欄位)

  • Accept-Range:可接收的位元組範圍
  • Location:讓客戶端重定向到的URI
  • Server:HTTP伺服器的安裝資訊

實體首部欄位(請求報文與響應報文的實體部分使用的首部欄位)

  • Allow:資源可支援的HTTP方法
  • Content-Type:實體主類的型別
  • Content-Encoding:實體主體適用的編碼方式
  • Content-Language:實體主體的自然語言
  • Content-Length:實體主體的位元組數
  • Content-Range:實體主體的位置範圍,一般用於發出部分請求時使用

4. HTTP1.0、HTTP1.1、HTTP2.0區別

HTTP1.0 和 HTTP1.1 主要區別

  1. 長連線

    • HTTP1.0需要使用keep-alive引數告知伺服器要建立一個長連線,而HTTP1.1預設支援長連線
    • HTTP是基於TCP/IP協議的,建立一個TCP連線是需要經過三次握手的,有一定的開銷,如果每次通訊都要重新建立連線的話,對效能有影響。因此最好能維持一個長連線,可以用這個長連線來發送多個請求
  2. 節約頻寬

    • HTTP1.1支援只發送header資訊,也就是HTTP的HEAD Method,如果伺服器認為客戶端有許可權請求伺服器,則返回100,否則返回401。客戶端如果接收到100,才開始把請求體body傳送到伺服器。
    • 這樣,當伺服器返回401的時候,客戶端就可以不用傳送請求體了,節約了頻寬
    • HTTP1.1支援分塊傳輸,比如206狀態碼,由Content-Range指定傳輸內容,這是支援檔案斷點續傳的基礎。
  3. HOST域

    • 現在一臺伺服器上可以有多個虛擬主機,這些虛擬站點可以共享同一個ip和埠,HTTP1.0是沒有host域的,HTTP1.1才支援這個引數

HTTP1.1 和 HTTP2.0的區別

  1. 多路複用

    • HTTP2.0使用了多路複用的技術,做到同一個連線併發處理多個請求,而且併發請求的數量比HTTP1.1大了好幾個數量級

      • 當然HTTP1.1也可以多建立幾個TCP連線,來支援處理更多併發的請求,但是建立TCP連線本身也是有開銷的
      • TCP連線有一個預熱和保護的過程,先檢查資料是否傳送成功,一旦成功過,則慢慢加大傳輸速度。因此對應瞬時併發的連線,伺服器的響應就會變慢。所以最好能使用一個建立的連線,並且這個連線可以支援瞬時併發的請求
      • HTTP/1.1,若干個請求排隊序列化單執行緒處理,後面的請求等待前面請求的返回才能獲得執行機會,一旦有某個請求超時,後續請求只能被阻塞,也就是人們常說的線頭阻塞
      • HTTP/2.0,多個請求可同時在一個連線上並行執行,某個任務耗時嚴重,不會影響到其他連線的正常執行
  2. 資料壓縮

    • HTTP1.1不支援header資料的壓縮,HTTP2.0使用HPACK演算法對header的資料進行壓縮,這樣資料體積小了,在網路上傳輸就會更快
  3. 伺服器推送

    • 當我們對HTTP2.0的web server請求資料的時候,伺服器會順便把一些客戶端需要的資源一起推送到客戶端,免得客戶端再次建立連線傳送請求到伺服器獲取。這種方式非常適合載入靜態資源。
    • 伺服器推送的這些資源其實存在客戶端的某個地方,客戶端直接從本地載入這些資源就可以了,不用走網路,速度自然快很多。

HTTP快取

快取分類

  • 強快取

瀏覽器在載入資源時,先根據這個資源的一些http header判斷它是否命中強快取,如果命中,瀏覽器直接從自己的快取中讀取資源,不會發請求到伺服器,此時狀態碼是200,但是看Size項是from memory cache或from disk cache

  • 協商快取
  • 當強快取沒有命中時,瀏覽器一定會發送一個請求到伺服器,通過伺服器端依據資源的另外一些http header驗證這個資源是否命中協商快取,如果命中,伺服器會將這個請求返回304,但是不會返回這個資源的資料,而是告訴客戶端可以直接從快取中載入這個資源,於是瀏覽器就又會從自己的快取中去載入這個資源;如果沒有命中,則將資源返回客戶端,狀態為200,瀏覽器同時依據response header中的相關項更新本地快取資料

from memory cache 和 from disk cache

區別
  1. from memory cache 是從記憶體中讀取快取資源,很快,關閉瀏覽器後,記憶體中的資源就消失了
  2. from disk cache 是從磁碟中讀取快取資源,要比 from memory cache 慢,但是持久化,關閉瀏覽器後仍然存在
哪些資源存在memory,哪些資源存在disk

看了一些文章,大部分觀點是說:

  1. 資源在disk和memory中都會存
  2. 當關閉瀏覽器,再開啟那個頁面的時候,從disk cache中獲取快取資源,同時將快取資源存在了記憶體中,當再次重新整理頁面的時候,就從memory cache中讀取,因為這樣會更快一些
  3. 我自己試了一些頁面,再次重新整理還是有的from disk cache,有的from memory cache,網站被黑,所以這個持保留觀點
  4. 還有的文章說css檔案存在disk中,js等指令碼存在memory中,個人認為這個不太靠譜,因為memory中的快取在關閉瀏覽器就消失了,如果js只存在memory,就起不到快取的作用了

強快取相關http header

  • Expires

Expires的值是服務端返回的到期時間,用GMT格式的字串表示,如:Expires: Thu, 31 Dec 2016 23:55:55 GMT。即下一次請求時,請求時間小於伺服器返回的到期時間,直接使用快取資料。不過Expires是HTTP1.0的東西,現在瀏覽器預設使用HTTP1.1,所以它的作用基本忽略。另一個問題是,到期時間是由伺服器生成的,但是客戶端時間可能和伺服器時間有偏差,這就會導致快取命中的誤差。所以HTTP1.1的版本中,使用Cache-Control替代。

  • Cache-Control

Cache-Control是最重要的規則。常見的取值有:

- ```private```:客戶端可以快取
- ```public```:客戶端和代理伺服器都可以快取
- ```max-age=xxx```:快取的內容將在xxx秒後失效,單位是秒
- ```no-cache```:需要使用**協商快取**來驗證快取資料
- ```no-store```:不快取

協商快取相關http header

第1組:Last-Modified/If-Modified—Since

  • Last-Modified:第一次請求資源時,伺服器返回的http header,告訴瀏覽器資源的最後修改時間,為GMT格式,如Last-Modified: Thu, 24 Jan 2017 23:55:55 GMT
  • If-Modified-Since:再次請求伺服器資源時,瀏覽器設定在請求header中,值 為該資源第一次請求時伺服器設定的Last-Modified`值,如If-Modified-Since: Thu, 24 Jan 2017 23:55:55 GMT,伺服器收到請求後發現request header中有If-Modified-Since,則與被請求資源的最後修改時間進行比對。若資源的最後修改時間大於If-Modified-Since,說明資源又被改動過,則返回資源內容,狀態碼200,同時瀏覽器依據相應response header更新快取資源;若資源的最後修改時間小於或等於If-Modified-Since,說明資源無新修改,則返回狀態碼304,但是不返回資源,告知瀏覽器繼續使用所儲存的cache

第2組:Etag/If-None-Match

  • Etag:伺服器響應請求時,告訴瀏覽器當前資源在伺服器的唯一標識(生成規則由伺服器確定),如Etag: W/"5886c231-8d9"
  • If-None-Match:再次請求伺服器時,通過此欄位告知伺服器該資源的唯一標識,如If-None-Match: W/"5886c231-8d9",伺服器收到請求後發現request header中有If-None-Match,則與被請求資源的唯一標識進行比對,若不同,說明資源又被改動過,則返回資源內容,狀態碼200,同時瀏覽器依據相應response header更新快取資源;若相同,則說明資源無更改,返回304,告知瀏覽器繼續使用所儲存的快取資源

為什麼要有Etag?

Last-Modified顆粒度是秒,只能記錄秒級的修改,比如1s內修改了N次,If-Modified-Since就無法判斷了,所以要引入Etag。

總結

  1. 先執行強快取策略,伺服器通知瀏覽器一個快取有效時間,在有效時間內,下次請求時直接使用快取,不發起http請求,快取從from memory cache或from disk cache中讀取,若超過了有效時間,則執行協商快取策略
  2. 對於協商快取,將快取資訊中的Etag和Last-Modified的值通過If-None-Match和If-Modified-Since傳送給伺服器,由伺服器進行校驗,若資源無更改,返回304,瀏覽器繼續使用快取,若資源被更改,則返回資源,狀態碼200,同時瀏覽器更新快取

流程圖

瀏覽器第一次請求:

瀏覽器第二次請求:

5. Http長連線keep-alive

三個概念

  1. 短連線

所謂短連線,就是每次請求一個資源就建立連線,請求完成後立馬關閉。每次請求都經過“建立TCP連線 -> 請求資源 -> 響應資源 -> 釋放連線”。

  1. 長連線

所謂長連線(persistent connection),就是隻建立一次TCP連線,多次HTTP請求都複用該連線。

  1. 並行連線

所謂並行連線(multiple connection),其實就是併發的短連線。

keep-alive

在HTTP/1.0裡,為了實現client到web-server能支援長連線,必須在HTTP請求頭裡顯式指定Connection: keep-alive

在HTTP/1.1裡,就預設開啟了keep-alive,要關閉keep-alive必須在HTTP請求頭裡顯式指定Connection: close

現在大多數瀏覽器都預設是使用HTTP/1.1,所以keep-alive都是預設開啟的。一旦client和server達成協議,那麼長連線就建立好了。

keepalive_timeout

Httpd守護程序,一般都提供了keep-alive timeout時間設定引數。比如nginx的keepalive_timeout,和Apache的KeepAliveTimeout。這個keepalive_timout時間值意味著:一個http產生的tcp連線在傳送完最後一個響應後,還需要hold住keepalive_timeout秒後,才開始關閉這個連線。Nginx配置中的keepalive_timeout預設為75s,

6. cookie與Session

這個重點在於理解,這裡就不贅述了。