網路協議之 - HTTP
前言
關於HTTP的知識比較繁雜,也比較零散,於是想要通過這篇文章對常用知識點進行總結,一些知識點描述是從網上搜集而來,如有侵權,可以聯絡我進行修改。
提出問題
- Http的報文結構。
- Http request的幾種型別。
- Http的狀態碼含義。
- Http1.1和Http1.0的區別,以及快取原理
- Http長連線keep-alive。
- Cookie與Session的作用於原理。
- 電腦上訪問一個網頁,整個過程是怎麼樣的:DNS、HTTP、TCP、OSPF、IP、ARP。
解答
1. Http的報文結構
http協議的請求報文和響應報文都是由以下4部分組成:
- 請求行
- 請求頭
- 空行 CR + LF,回車 + 換行
- 請求體
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 OK
、HTTP/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 主要區別
-
長連線
- HTTP1.0需要使用keep-alive引數告知伺服器要建立一個長連線,而HTTP1.1預設支援長連線
- HTTP是基於TCP/IP協議的,建立一個TCP連線是需要經過三次握手的,有一定的開銷,如果每次通訊都要重新建立連線的話,對效能有影響。因此最好能維持一個長連線,可以用這個長連線來發送多個請求
-
節約頻寬
- HTTP1.1支援只發送header資訊,也就是HTTP的HEAD Method,如果伺服器認為客戶端有許可權請求伺服器,則返回100,否則返回401。客戶端如果接收到100,才開始把請求體body傳送到伺服器。
- 這樣,當伺服器返回401的時候,客戶端就可以不用傳送請求體了,節約了頻寬
- HTTP1.1支援分塊傳輸,比如206狀態碼,由Content-Range指定傳輸內容,這是支援檔案斷點續傳的基礎。
-
HOST域
- 現在一臺伺服器上可以有多個虛擬主機,這些虛擬站點可以共享同一個ip和埠,HTTP1.0是沒有host域的,HTTP1.1才支援這個引數
HTTP1.1 和 HTTP2.0的區別
-
多路複用
-
HTTP2.0使用了多路複用的技術,做到同一個連線併發處理多個請求,而且併發請求的數量比HTTP1.1大了好幾個數量級
- 當然HTTP1.1也可以多建立幾個TCP連線,來支援處理更多併發的請求,但是建立TCP連線本身也是有開銷的
- TCP連線有一個預熱和保護的過程,先檢查資料是否傳送成功,一旦成功過,則慢慢加大傳輸速度。因此對應瞬時併發的連線,伺服器的響應就會變慢。所以最好能使用一個建立的連線,並且這個連線可以支援瞬時併發的請求
- HTTP/1.1,若干個請求排隊序列化單執行緒處理,後面的請求等待前面請求的返回才能獲得執行機會,一旦有某個請求超時,後續請求只能被阻塞,也就是人們常說的線頭阻塞
- HTTP/2.0,多個請求可同時在一個連線上並行執行,某個任務耗時嚴重,不會影響到其他連線的正常執行
-
-
資料壓縮
- HTTP1.1不支援header資料的壓縮,HTTP2.0使用HPACK演算法對header的資料進行壓縮,這樣資料體積小了,在網路上傳輸就會更快
-
伺服器推送
- 當我們對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
區別
- from memory cache 是從記憶體中讀取快取資源,很快,關閉瀏覽器後,記憶體中的資源就消失了
- from disk cache 是從磁碟中讀取快取資源,要比 from memory cache 慢,但是持久化,關閉瀏覽器後仍然存在
哪些資源存在memory,哪些資源存在disk
看了一些文章,大部分觀點是說:
- 資源在disk和memory中都會存
- 當關閉瀏覽器,再開啟那個頁面的時候,從disk cache中獲取快取資源,同時將快取資源存在了記憶體中,當再次重新整理頁面的時候,就從memory cache中讀取,因為這樣會更快一些
- 我自己試了一些頁面,再次重新整理還是有的from disk cache,有的from memory cache,網站被黑,所以這個持保留觀點
- 還有的文章說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。
總結
- 先執行強快取策略,伺服器通知瀏覽器一個快取有效時間,在有效時間內,下次請求時直接使用快取,不發起http請求,快取從from memory cache或from disk cache中讀取,若超過了有效時間,則執行協商快取策略
- 對於協商快取,將快取資訊中的Etag和Last-Modified的值通過If-None-Match和If-Modified-Since傳送給伺服器,由伺服器進行校驗,若資源無更改,返回304,瀏覽器繼續使用快取,若資源被更改,則返回資源,狀態碼200,同時瀏覽器更新快取
流程圖
瀏覽器第一次請求:
瀏覽器第二次請求:
5. Http長連線keep-alive
三個概念
- 短連線
所謂短連線,就是每次請求一個資源就建立連線,請求完成後立馬關閉。每次請求都經過“建立TCP連線 -> 請求資源 -> 響應資源 -> 釋放連線”。
- 長連線
所謂長連線(persistent connection),就是隻建立一次TCP連線,多次HTTP請求都複用該連線。
- 並行連線
所謂並行連線(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
這個重點在於理解,這裡就不贅述了。