一. 基礎概念
HTTP 特色
- 簡單快速:請求服務時,只需傳送請求方法和路徑
- 靈活:容許傳輸任意類型的數據對象,由 Content-Type 標記
- 無鏈接:服務端處理完請求就斷開鏈接
- 無狀態:意味着每一個請求都是獨立的,若是後續處理須要前面的信息,則它必須重傳
持久鏈接 Keep-Alive
- connection: **Keep-Alive **使客戶端到服務器端的鏈接持續有效,避免了創建或者從新創建鏈接,超過 Keep-Alive 規定的時間,意外斷電等狀況除外
- 請求 1 -> 響應 1 -> 請求 2 -> 響應 2
- HTTP 1.1
管線化
- 經過持久鏈接完成
- 請求 1 -> 請求 2 -> 請求 3 -> 響應 1 -> 響應 2 -> 響應 3
- 只有 GET 和 HEAD 能夠進行管線化,POST 則有所限制
- HTTP 1.1
GET 和 POST 區別
- GET 請求在 URL 中傳送的參數是有長度限制的,而 POST 麼有
- GET 比 POST 更不安全,由於參數直接暴露在 URL 上,因此不能用來傳遞敏感信息
- GET 參數經過 URL 傳遞,POST 放在 Request body 中
- GET 在瀏覽器回退時是無害的,而 POST 會再次提交請求
- GET 產生的 URL 地址能夠被收藏,而 POST 不能夠
- GET 請求會被瀏覽器主動緩存,而 POST 不會,除非手動設置
- GET 請求參數會被完整保留在瀏覽器歷史記錄裏,而 POST 中的參數不會被保留
- GET 請求只能進行 url 編碼,而 POST 支持多種編碼方式
經常使用狀態碼
- 200 OK:請求已正常處理
- 204 No Content:請求處理成功,但沒有任何資源能夠返回給客戶端
- 301 Moved Permanently:永久重定向
- 302 Found:臨時性重定向
- 304 Not Modified:資源未修改,不返回資源,容許客戶端訪問緩存資源
- 400 Bad Request:請求參數有誤
- 401 Unauthorized:要求用戶身份認證要求
- 403 Forbidden:服務器理解請求,但拒絕執行請求
- 404 Not Found:服務器上沒有請求的資源。路徑錯誤等
- 408 Request Time-out:請求超時
- 500 Internal Server Error:服務器內部錯誤
二. 三次握手與四次揮手
三次握手
假如是兩次握手
1. C:喂喂喂,我是 C,你聽的到嗎?
2. S:在在在,我能聽到,我是 S,你能聽到我嗎?
3. C:(聽到了,老子不想理你)
4. S:喂喂喂?聽不聽到?我 X,對面死了,我掛了。。
複製代碼
假如是四次握手
1. C:喂喂喂,我是 C,你聽的到嗎?
2. S:在在在,我能聽到,我是 S,你能聽到我嗎?
3. C:聽到了,你呢?你能聽到嗎?
4. S:??你是智障?我不是說了我能聽到嗎,不想跟 xx 說話。。。
複製代碼
三次握手
1. C:喂喂喂,我是 C,你聽的到嗎?
2. S:在在在,我能聽到,我是 S,你能聽到我嗎?
3. C:聽到了。咱們今天去釣魚吧。。balabala
複製代碼
總結
1. 第一次握手,C 端發送 S 端接收到,證實了 C 端的發送能力
2. 第二次握手,S 端發送 C 端接收到,證實了 S 端的接收能力和發送能力
3. 第三次握手,C 端發送 S 端接收到,證實了 C 端的接收能力
4. 在可靠的同時,還要考慮性能和時間問題,因此三次握手最合理
複製代碼
四次揮手
全雙工
A 和 B 能夠互相通訊,類比發短信,同一時間雙方均可以發信息給對方,互不影響前端
單雙工
A 和 B 只能單向通訊,類比打電話,同一時間只能一人說話,另外一人聽,若是兩人一塊兒說話,那誰都聽不清楚了,沒有意義瀏覽器
四次揮手
1. C:很差意思 S,我這邊須要關閉鏈接了,你準備一下?
2. S:好的 C,我收到你的關閉信號了,我還有數據沒發好,你等我下。
3. S:C 老弟,我能夠關閉了,給你最後說一下,等下你迴應個人話,我就直接關了;
4. C:好的老哥,我回應你一下,你收到就關閉吧,不用理我
5. S:(收到 ack 信息,直接就關閉了),此過程不產生數據的交互,不算揮手次數
6. C:等待 2MSL(最大報文段生存時間)後,S 沒東西給過來,我也關了;
複製代碼
與三次握手的區別
四次揮手的中間兩次揮手至關於把三次握手的中間一次握手拆分爲兩次緩存
爲何 C 端須要等最大報文生存時間後才能關閉?
擔憂網絡不可靠而致使的丟包,超過了最大等待時間的話,就算收不到也沒用了,因此就能夠關閉了。安全
三. 緩存
Expires(強緩存)
- HTTP 1.0 字段,表示緩存到期時間,一個絕對時間
Expires: Thu, 10 Nov 2020 08:45:11 GMT
複製代碼
- 缺點:若用戶修改本地時間,則可能致使瀏覽器判斷緩存失效
Cache-control(強緩存)
- HTTP 1.1 字段,表示資源緩存的最大有效時間(秒),在該時間內,客戶端不須要向服務器發送請求,優先級高於 Expires
Cache-control:public, max-age=2592000
複製代碼
- max-age:即最大有效時間
- s-maxage:用於代理緩存(好比 CDN 緩存),優先級大於 max-age
- must-revalidate:若是超過了 max-age 的時間,瀏覽器必須向服務器發送請求,驗證資源是否還有效
- no-cache:瀏覽器緩存內容,但不直接使用,使用時向服務器發請求確認
- no-store:不進行任何緩存
- public:全部的內容均可以被緩存 (包括客戶端和代理服務器, 如 CDN)
- privite:全部的內容只有客戶端才能夠緩存(默認值)
- max-age=0, must-revalidate 和 no-cache 等價
Last-Modified & If-Modified-Since(弱緩存)
- 服務器經過 Response Headers 的 Last-Modified 字段告知客戶端,資源最後一次被修改的時間
Last-Modified: Mon, 10 Nov 2020 09:10:11 GMT
複製代碼
- 下一次請求相同資源時,瀏覽器從本身的緩存中找出「不肯定是否過時的」緩存。所以在 Request Headers 中將上次的 Last-Modified 的值寫入到請求頭的 If-Modified-Since 字段
If-Modified-Since: Mon, 10 Nov 2020 09:10:11 GMT
複製代碼
- 服務器會將 If-Modified-Since 的值與 Last-Modified 字段進行對比。若是相等,則表示未修改,響應 304,繼續返回 Last-Modified 字段;反之,則表示修改了,響應 200 狀態碼,並返回數據以及新的 Last-Modified 字段
- 缺點:
- 某些服務器沒法獲取精準時間
- 若是資源更新的速度是秒如下單位,那麼該緩存是不能被使用的,由於它的時間單位最低是秒
- 若是文件是經過服務器動態生成的,那麼該方法的更新時間永遠是生成的時間,儘管文件可能沒有變化,因此起不到緩存的做用
Etag & If-None-Match(弱緩存)
- Etag 存儲的是文件的特殊標識(通常都是 hash 或 MD5 生成的),服務器存儲着文件的 Etag 字段,
ETag: "asj1jbasdbb4skdbk-ajs"
複製代碼
- 流程與 Last-Modified & If-Modified-Since 一致
If-None-Match: "asj1jbasdbb4skdbk-ajs"
複製代碼
- Etag 的優先級高於 Last-Modified
- 更爲嚴謹,文件變換及 Etag 變化
分級緩存策略
- 200 from cache:最底層,由 Expires、Cache-control 控制(Cache-control 優先級大於 Expires),若命中緩存則直接讀取,若沒有命中,則進入下一狀態
- 304:這一層由 Last-Modified、Etag 控制(Etag 優先級大於 Last-Modified),若服務器校驗經過,返回 304 及舊的 Last-Modified、Etag 字段,瀏覽器讀取緩存;若服務器校驗不經過,進入下一狀態
- 200:若服務器校驗不經過,或用戶強制刷新頁面,則返回 200 和文件以及新的 Last-Modified、Etag 字段,瀏覽器更新緩存
總結
- Expires、Cache-control、Last-Modified & If-Modified-Since、Etag & If-None-Match 均以時間秒爲維度,而 Etag & If-None-Match 則是以文件爲維度,因此 Etag 最爲嚴謹,文件變化 Etag 就會變化
- 優先級:Cache-control > Expires > Etag > Last-Modified
四. 參考文章
一文讀懂前端緩存bash
本文大部分爲本身總結,部分示例時參考了一些文章,但因誤刪了瀏覽器歷史記錄,致使部分參考文章沒法找回,如有知情者請與我聯繫,我會補上原文連接。服務器