最近面試咋常問HTTP

推薦一下極客時間的《透視HTTP協議》,記錄專欄中一些比較重要的點。若有侵權,請聯繫我。javascript

開篇詞

To Be a HTTP Hero

破冰篇

時勢與英雄:HTTP的前世此生

講解了HTTP發展的趨勢 從HTTP 0.9到HTTP1.0(不做爲正式使用)到HTTP1.1 (如今主流)到HTTP2 (2014產生)到HTTP3(QUIC協議推進發展) HTTP2和HTTP3主要是由谷歌需求推進協議發展。css

HTTP0.9

  1. 採用純文本形式
  2. 只容許使用GET獲取資源,得到後就斷開鏈接

HTTP1.0

  1. 增長了 HEAD、POST 等新方法;
  2. 增長了響應狀態碼,標記可能的錯誤緣由;
  3. 引入了協議版本號概念;
  4. 引入了 HTTP Header(頭部)的概念,讓 HTTP 處理請求和響應更加靈活;
  5. 傳輸的數據再也不僅限於文本。

HTTP1.1

  1. 增長了 PUT、DELETE 等新的方法;
  2. 增長了緩存管理和控制;
  3. 明確了鏈接管理,容許持久鏈接;
  4. 容許響應數據分塊(chunked),利於傳輸大文件;
  5. 強制要求 Host 頭,讓互聯網主機託管成爲可能。

緩存管理和控制:當瀏覽器得到資源後,服務器回傳資源有效時間,瀏覽器將參數放在Cache-Control中下次請求時判斷緩存是否過時再次請求html

HTTP2

  1. 二進制協議,再也不是純文本;
  2. 可發起多個請求,廢棄了 1.1 裏的管道;
  3. 使用專用算法壓縮頭部,減小數據傳輸量;
  4. 容許服務器主動向客戶端推送數據;
  5. 加強了安全性,「事實上」要求加密通訊。

HTTP3

HTTP是什麼?HTTP又不是什麼?

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

HTTP世界全覽(上):與HTTP相關的各類概念

image-20200424162001087

  1. 互聯網上絕大部分資源都使用 HTTP 協議傳輸;
  2. 瀏覽器是 HTTP 協議裏的請求方,即 User Agent;
  3. 服務器是 HTTP 協議裏的應答方,經常使用的有 Apache 和 Nginx;
  4. CDN 位於瀏覽器和服務器之間,主要起到緩存加速的做用;
  5. 爬蟲是另外一類 User Agent,是自動訪問網絡資源的程序。

HTTP世界全覽(下):與HTTP相關的各類協議

image-20200424162946245

代理的做用

  1. 負載均衡:把訪問請求均勻分散到多臺機器,實現訪問集羣化;
  2. 內容緩存:暫存上下行的數據,減輕後端的壓力;
  3. 安全防禦:隱匿 IP, 使用 WAF 等工具抵禦網絡攻擊,保護被代理的機器;
  4. 數據處理:提供壓縮、加密等額外的功能。

常說的「四層」和「七層」究竟是什麼?「五層」「六層」哪去了?

TCP是有狀態的協議,發送數據前雙方必須創建鏈接,由此能夠保證傳輸字節流 是連續的並且沒有重複。UDP是沒有狀態的協議,發送前不須要創建鏈接。UDP發送的數據包是無序的,且亂序收的。算法

CDN處於應用層 (一開始覺得處於網絡層,果真對於請求處理層數越少越好)json

域名裏有哪些門道

  1. 域名使用字符串來代替 IP 地址,方便用戶記憶,本質上一個名字空間系統;
  2. DNS 就像是咱們現實世界裏的電話本、查號臺,統管着互聯網世界裏的全部網站,是一 個「超級大管家」;
  3. DNS 是一個樹狀的分佈式查詢系統,但爲了提升查詢效率,外圍有多級的緩存;
  4. 使用 DNS 能夠實現基於域名的負載均衡,既能夠在內網,也能夠在外網。

DNS域名解析的過程能夠分別爲本地host文件-> 本地域名服務器->根域名服務器->權威域名服務器後端

外圍有多級緩存爲大公司爲了加速域名解析,會建立本身的DNS域名服務器,非權威域名服務器。做爲用戶DNS查詢的代理,代替用戶訪問核心DNS。如同谷歌建立的8.8.8.8免費公共域名服務器。瀏覽器

本身動手,搭建HTTP實驗環境

配置實驗環境 ,同時安裝了wireshak以及openresty緩存

基礎篇

鍵入網址再按下回車,後面究竟發生了什麼?

再簡要敘述一下此次最簡單的瀏覽器 HTTP 請求過程:安全

  1. 瀏覽器從地址欄的輸入中得到服務器的 IP 地址和端口號;
  2. 瀏覽器用 TCP 的三次握手與服務器創建鏈接;
  3. 瀏覽器向服務器發送拼好的報文;
  4. 服務器收到報文後處理請求,一樣拼好報文再發給瀏覽器;
  5. 瀏覽器解析報文,渲染輸出頁面。

image-20200424221950118

HTTP報文是什麼樣子的?

HTTP協議主要由如下三部分構成

  1. 起始行
  2. 頭部字段集合
  3. 消息正文

image-20200425092339944

HTTP協議再細分能夠分爲 請求以及響應

請求行包括

  • 請求方法
  • 請求目標
  • HTTP協議版本號

這三個部分一般用空格來進行隔開,最後用CRLF來表示結束

狀態行包括

  • HTTP協議版本
  • 狀態碼
  • 緣由 (如ok等)

image-20200425092834693

頭部字段主要分爲四大類

  1. 通用字段:在請求頭和響應頭裏均可以出現;
  2. 請求字段:僅能出如今請求頭裏,進一步說明請求信息或者額外的附加條件;
  3. 響應字段:僅能出如今響應頭裏,補充說明響應報文的信息;
  4. 實體字段:它實際上屬於通用字段,但專門描述 body 的額外信息。

請求字段:

Host字段:告訴服務器這個請求應該由哪一個主機來處理

User-Agent字段:告訴服務器請求的客戶端信息

通用字段:

Data字段:客戶端可使用這個時間再搭配其餘字段決定緩存策略

響應字段:

Server字段:告訴客戶端 響應服務器信息(也有部分網站不用透露信息)

實體字段:

content-length:表示響應體中報文body的長度

總結

  1. HTTP 報文結構就像是「大頭兒子」,由「起始行 + 頭部 + 空行 + 實體」組成,簡單地說就是「header+body」;
  2. HTTP 報文能夠沒有 body,但必需要有 header,並且 header 後也必需要有空行,形象地說就是「大頭」必需要帶着「脖子」;
  3. 請求頭由「請求行 + 頭部字段」構成,響應頭由「狀態行 + 頭部字段」構成;
  4. 請求行有三部分:請求方法,請求目標和版本號;
  5. 狀態行也有三部分:版本號,狀態碼和緣由字符串;
  6. 頭部字段是 key-value 的形式,用「:」分隔,不區分大小寫,順序任意,除了規定的標準頭,也能夠任意添加自定義字段,實現功能擴展;
  7. HTTP/1.1 裏惟一要求必須提供的頭字段是 Host,它必須出如今請求頭裏,標記虛擬主機名。

應該如何理解請求方法?

HTTP/1.1 規定了八種方法

  1. GET:獲取資源,能夠理解爲讀取或者下載數據;
  2. HEAD:獲取資源的元信息;
  3. POST:向資源提交數據,至關於寫入或上傳數據;
  4. PUT:相似 POST;
  5. DELETE:刪除資源;
  6. CONNECT:創建特殊的鏈接隧道;
  7. OPTIONS:列出可對資源實行的方法;
  8. TRACE:追蹤請求 - 響應的傳輸路徑。

GET POST DELETE PUT 不用過多介紹

HEAD

HEAD方法與 GET 方法相似,也是請求從服務器獲取資源,服務器的處理機制也是同樣的,但服務器不會返回請求的實體數據,只會傳回響應頭,也就是資源的「元信息」。

HEAD 方法能夠看作是 GET 方法的一個「簡化版」或者「輕量版」。由於它的響應頭與 GET 徹底相同,因此能夠用在不少並不真正須要資源的場合,避免傳輸 body 數據的浪費。

安全與冪等

對於安全性來講GET和HEAD是安全的,不會修改計算機的資源。剩下三種會修改或者刪除計算機的資源因此不是安全的。

對於冪等性來講GET和HEAD是冪等的。同時PUT DELETE方法也是冪等的,屢次修改一條記錄最後的結果也是一條,而POST則會修改數據的個數 不是冪等的。

總結:

  1. 請求方法是客戶端發出的、要求服務器執行的、對資源的一種操做;
  2. 請求方法是對服務器的「指示」,真正應如何處理由服務器來決定;
  3. 最經常使用的請求方法是 GET 和 POST,分別是獲取數據和發送數據;
  4. HEAD 方法是輕量級的 GET,用來獲取資源的元信息;
  5. PUT 基本上是 POST 的同義詞,多用於更新數據;
  6. 「安全」與「冪等」是描述請求方法的兩個重要屬性,具備理論指導意義,能夠幫助咱們設計系統。

你能寫出正確的網址嗎?

URI,也就是統一資源標識符Uniform Resource Identifier)

URL——統一資源定位符Uniform Resource Locator)

URL 實在是太普及了,因此經常把這二者簡單地視爲相等。

URL組成的基本格式

image-20200425141632553

瀏覽器會根據cheme使用默認的端口號 (HTTP 80 端口,HTTPS 443端口)

總結

  1. URI 是用來惟一標記服務器上資源的一個字符串,一般也稱爲 URL;
  2. URI 一般由 scheme、host:port、path 和 query 四個部分組成,有的能夠省略;
  3. scheme 叫「方案名」或者「協議名」,表示資源應該使用哪一種協議來訪問;
  4. 「host:port」表示資源所在的主機名和端口號;
  5. path 標記資源所在的位置;
  6. query 表示對資源附加的額外要求;
  7. 在 URI 裏對「@&/」等特殊字符和漢字必需要作編碼,不然服務器收到 HTTP 報文後會沒法正確處理。

響應狀態碼該怎麼用?

狀態碼的分類爲

  • 1××:提示信息,表示目前是協議處理的中間狀態,還須要後續的操做;
  • 2××:成功,報文已經收到並被正確處理;
  • 3××:重定向,資源位置發生變更,須要客戶端從新發送請求;
  • 4××:客戶端錯誤,請求報文有誤,服務器沒法處理;
  • 5××:服務器錯誤,服務器在處理請求時內部發生了錯誤。

1××

1××類狀態碼屬於提示信息,是協議處理的中間狀態,實際可以用到的時候不多。

2××

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

200 OK」是最多見的成功狀態碼,表示一切正常,服務器如客戶端所指望的那樣返回了處理結果,若是是非 HEAD 請求,一般在響應頭後都會有 body 數據。

204 No Content」是另外一個很常見的成功狀態碼,它的含義與「200 OK」基本相同,但響應頭後沒有 body 數據。因此對於 Web 服務器來講,正確地區分 200 和 204 是很必要的。

206 Partial Content」是 HTTP 分塊下載或斷點續傳的基礎,在客戶端發送「範圍請求」、要求獲取資源的部分數據時出現,它與 200 同樣,也是服務器成功處理了請求,但 body 裏的數據不是資源的所有,而是其中的一部分。

3××

3××類狀態碼錶示客戶端請求的資源發生了變更,客戶端必須用新的 URI 從新發送請求獲取資源,也就是一般所說的「重定向」,包括著名的 30一、302 跳轉。

301 Moved Permanently」俗稱「永久重定向」,含義是這次請求的資源已經不存在了,須要改用改用新的 URI 再次訪問。

與它相似的是「302 Found」,曾經的描述短語是「Moved Temporarily」,俗稱「臨時重定向」,意思是請求的資源還在,但須要暫時用另外一個 URI 來訪問。

4××

4××類狀態碼錶示客戶端發送的請求報文有誤,服務器沒法處理,它就是真正的「錯誤碼」含義了。

400 Bad Request」是一個通用的錯誤碼,表示請求報文有錯誤,但具體是數據格式錯誤、缺乏請求頭仍是 URI 超長它沒有明確說,只是一個籠統的錯誤,

403 Forbidden」實際上不是客戶端的請求出錯,而是表示服務器禁止訪問資源。緣由可能多種多樣,例如信息敏感、法律禁止等,若是服務器友好一點

404 Not Found」多是咱們最常看見也是最不肯意看到的一個狀態碼,它的原意是資源在本服務器上未找到

5××

5××類狀態碼錶示客戶端請求報文正確,但服務器在處理時內部發生了錯誤,沒法返回應有的響應數據,是服務器端的「錯誤碼」。

500 Internal Server Error」與 400 相似,也是一個通用的錯誤碼

501 Not Implemented」表示客戶端請求的功能還不支持

502 Bad Gateway」一般是服務器做爲網關或者代理時返回的錯誤碼

503 Service Unavailable」表示服務器當前很忙,暫時沒法響應服務,咱們上網時有時候遇到的「網絡服務正忙,請稍後重試」的提示信息就是狀態碼 503

總結

  1. 狀態碼在響應報文裏表示了服務器對請求的處理結果;
  2. 狀態碼後的緣由短語是簡單的文字描述,能夠自定義;
  3. 狀態碼是十進制的三位數,分爲五類,從 100 到 599;
  4. 2××類狀態碼錶示成功,經常使用的有 200、20四、206;
  5. 3××類狀態碼錶示重定向,經常使用的有 30一、30二、304;
  6. 4××類狀態碼錶示客戶端錯誤,經常使用的有 400、40三、404;
  7. 5××類狀態碼錶示服務器錯誤,經常使用的有 500、50一、50二、503。

HTTP有哪些特色?

總結

  1. HTTP 是靈活可擴展的,能夠任意添加頭字段實現任意功能;
  2. HTTP 是可靠傳輸協議,基於 TCP/IP 協議「儘可能」保證數據的送達;
  3. HTTP 是應用層協議,比 FTP、SSH 等更通用功能更多,可以傳輸任意數據;
  4. HTTP 使用了請求 - 應答模式,客戶端主動發起請求,服務器被動回覆請求;
  5. HTTP 本質上是無狀態的,每一個請求都是互相獨立、毫無關聯的,協議不要求客戶端或服務器記錄請求相關的信息。

HTTP雖然是可靠的傳輸協議但不保證傳輸的時候是徹底有效的,想要徹底可靠,須要使用中間件消息隊列等。

HTTP有哪些優勢?又有哪些缺點?

總結

  1. HTTP 最大的優勢是簡單、靈活和易於擴展;
  2. HTTP 擁有成熟的軟硬件環境,應用的很是普遍,是互聯網的基礎設施;
  3. HTTP 是無狀態的,能夠輕鬆實現集羣化,擴展性能,但有時也須要用 Cookie 技術來實現「有狀態」;
  4. HTTP 是明文傳輸,數據徹底肉眼可見,可以方便地研究分析,但也容易被竊聽;
  5. HTTP 是不安全的,沒法驗證通訊雙方的身份,也不能判斷報文是否被竄改;
  6. HTTP 的性能不算差,但不徹底適應如今的互聯網,還有很大的提高空間。

進階篇

海納百川:HTTP的實體數據(乾貨)

數據類型和壓縮

當請求返回的時候,TCP和IP任務已經完成可是HTTP須要解析出響應文件的類型。同時HTTP文件內容在傳輸時候常常會有壓縮。所以產生數據類型和壓縮類型的需求。

HTTP支持壓縮類型有:

  1. gzip:GNU zip 壓縮格式,也是互聯網上最流行的壓縮格式;
  2. deflate:zlib(deflate)壓縮格式,流行程度僅次於 gzip;
  3. br:一種專門爲 HTTP 優化的新壓縮算法(Brotli)。

HTTP常見數據類型有:

  1. text:即文本格式的可讀數據,咱們最熟悉的應該就是 text/html 了,表示超文本文檔,此外還有純文本 text/plain、樣式表 text/css 等。
  2. image:即圖像文件,有 image/gif、image/jpeg、image/png 等。
  3. audio/video:音頻和視頻數據,例如 audio/mpeg、video/mp4 等。
  4. application:數據格式不固定,多是文本也多是二進制,必須由上層應用程序來解釋。常見的有 application/json,application/javascript、application/pdf 等,另外,若是實在是不知道數據是什麼類型,像剛纔說的「黑盒」,就會是 application/octet-stream,即不透明的二進制數據。

HTTP 協議爲此定義了兩個 Accept 請求頭字段和兩個 Content 實體頭字段,用於客戶端和服務器進行「內容協商」。也就是說,客戶端用 Accept 頭告訴服務器但願接收什麼樣的數據,而服務器用 Content 頭告訴客戶端實際發送了什麼樣的數據。

image-20200425160429455

語言類型與編碼

爲了解決瀏覽器可以解析出正確的語言。爲此引入了語言類型和編碼。

Accept-language:指定了用戶使用想要使用的語言類型 (可有多個參數)

Accept-Language: zh-CN, zh, en

Content-Language:返回瀏覽器的語言類型

Content-Language: zh-CN

字符集在 HTTP 裏使用的請求頭字段是Accept-Charset,但響應頭裏卻沒有對應的 Content-Charset,而是在Content-Type字段的數據類型後面用「charset=xxx」來表示,這點須要特別注意。

image-20200425161104951

總結

image-20200425161221854

  1. 數據類型表示實體數據的內容是什麼,使用的是 MIME type,相關的頭字段是 Accept 和 Content-Type;
  2. 數據編碼表示實體數據的壓縮方式,相關的頭字段是 Accept-Encoding 和 Content-Encoding;
  3. 語言類型表示實體數據的天然語言,相關的頭字段是 Accept-Language 和 Content-Language;
  4. 字符集表示實體數據的編碼方式,相關的頭字段是 Accept-Charset 和 Content-Type;
  5. 客戶端須要在請求頭裏使用 Accept 等頭字段與服務器進行「內容協商」,要求服務器返回最合適的數據;
  6. Accept 等頭字段能夠用「,」順序列出多個可能的選項,還能夠用「;q=」參數來精確指定權重。

HTTP傳輸大文件的方法

主要方法有兩種,壓縮以及分塊傳輸

壓縮的三種算法中gzip壓縮率能夠達到百分之60,而br算法對於HTML文件壓縮效率在gzip基礎上還能夠提高百分之20。

分塊傳輸(重點)

若使用分塊傳輸那麼響應報文會添加Transfer-Encoding以及Content-length。「Transfer-Encoding: chunked」和「Content-Length」這兩個字段是互斥的,也就是說響應報文裏這兩個字段不能同時出現,一個響應報文的傳輸要麼是長度已知,要麼是長度未知(chunked)。

範圍請求

HTTP 協議爲了知足視頻跳點觀看的需求,提出了「範圍請求」(range requests)的概念,範圍請求不是 Web 服務器必備的功能,能夠實現也能夠不實現,因此服務器必須在響應頭裏使用字段「Accept-Ranges: bytes」明確告知客戶端:「我是支持範圍請求的」。

排隊也要講效率:HTTP的鏈接管理

主要內容短鏈接 長鏈接 隊頭阻塞

短鏈接

短鏈接對應版本爲HTTP0.9 指使用HTTP進行通訊時,二者每次傳送數據都要創建TCP鏈接,短鏈接的缺點嚴重製約了服務器的服務能力。

長鏈接

對於短鏈接的缺陷,HTTP1.1提出屢次請求只需創建一次TCP鏈接,減小服務器的消耗。使用的字段是Connection,值是「keep-alive」。長時間的空閒鏈接也會佔據服務器的資源,因此長鏈接也須要在適當的時間關閉。一般有兩種方式來在適當時間關閉請求,在必定請求後關閉鏈接 在設定空閒時間內無請求關閉鏈接

隊頭阻塞

隊頭阻塞主要是由於網絡模型爲「請求-應答」模型。前面的未響應請求對阻塞後方請求。對於HTTP來講可使用 併發鏈接來解決,對於同一個域名創建多個鏈接。(多個鏈接會加重服務器資源消耗被服務器當成攻擊拒絕鏈接)

總結

  1. 早期的 HTTP 協議使用短鏈接,收到響應後就當即關閉鏈接,效率很低;
  2. HTTP/1.1 默認啓用長鏈接,在一個鏈接上收發多個請求響應,提升了傳輸效率;
  3. 服務器會發送「Connection: keep-alive」字段表示啓用了長鏈接;
  4. 報文頭裏若是有「Connection: close」就意味着長鏈接即將關閉;
  5. 過多的長鏈接會佔用服務器資源,因此服務器會用一些策略有選擇地關閉長鏈接;
  6. 「隊頭阻塞」問題會致使性能降低,能夠用「併發鏈接」和「域名分片」技術緩解。

HTTP的重定向和跳轉(乾貨)

在網頁中由用戶主動發起請求的跳轉稱爲 主動跳轉,用戶沒法控制的稱爲 被動跳轉 ,同時也被稱爲 重定向

image-20200425212750598

這裏出現了一個新的頭字段「Location: /index.html」,它就是 301/302 重定向跳轉的祕密所在。

Location」字段屬於響應字段,必須出如今響應報文裏。但只有配合 301/302 狀態碼纔有意義,它標記了服務器要求重定向的 URI

對於站內的連接可使用 相對URl 站外的連接必須使用 絕對URI

301 以及 302

在重定向狀態碼中重用的分別爲301以及302。 301稱爲「永久重定向」 302稱爲「臨時重定向」 。

永久重定向指當運行服務器進行更新以及修改,資源位置徹底改變時使用

臨時重定向指當系統進行維修或者在服務降級時進行調用

對於瀏覽器來講 永久和臨時的區別在於對於永久性的重定向,瀏覽器下次該地址時會進行優化。對於臨時,瀏覽器在下次訪問的時候只會認爲該地址暫時沒法使用,下次請求時仍會使用原來URL。

HTTP的Cookie機制(乾貨)

HTTP增長Cookie是爲了解決HTTP是無狀態鏈接的問題。爲此HTTP中增長響應頭字段Set-Cookie和請求頭字段Cookie。Cookie是存儲在客戶端也就是瀏覽器中,只在本瀏覽器內生效。

在Cookie中也能夠設置其餘cookie屬性如cookie過時時間,可使用 Expires 和 Max-Age 兩個屬性來設置。

Expires爲絕對過時時間,爲某個絕對時間點。 Max-Age爲相對過時時間在某個時間點上延長必定時間。瀏覽器會優先使用 Max-Age做爲過時的時間。

對於cookie的安全性,可使用另外一個屬性「SameSite」防範「跨站請求僞造」(XSRF)攻擊。屬性「HttpOnly」會告訴瀏覽器,此 Cookie 只能經過瀏覽器 HTTP 協議傳輸,禁止其餘方式訪問。

總結

  1. Cookie 是服務器委託瀏覽器存儲的一些數據,讓服務器有了「記憶能力」;
  2. 響應報文使用 Set-Cookie 字段發送「key=value」形式的 Cookie 值;
  3. 請求報文裏用 Cookie 字段發送多個 Cookie 值;
  4. 爲了保護 Cookie,還要給它設置有效期、做用域等屬性,經常使用的有 Max-Age、Expires、Domain、HttpOnly 等;
  5. Cookie 最基本的用途是身份識別,實現有狀態的會話事務。

生鮮速遞:HTTP的緩存控制(乾貨)

這篇文章感受比較乾貨,建議看原文

服務器有緩存,瀏覽器也有緩存。緩存有什麼做用,又是經過哪幾個字段來保證有效,就是這篇文章的全部內容。

當使用瀏覽器的前進或者後退的時候,這時使用了緩存。在緩存期內瀏覽器有時仍會請求服務器獲取資源,由於緩存的使用是服務器和瀏覽器協商的結果。

image-20200426101004521

緩存的字段有以下幾個

  • max-age:緩存使用的最大有效時間,注意max-age爲ttl(time to live)當服務器響應時開始計時;

  • no_store:不容許緩存,用於某些變化很是頻繁的數據,例如秒殺頁面;

  • no_cache:它的字面含義容易與 no_store 搞混,實際的意思並非不容許緩存,而是能夠緩存,但在使用以前必需要去服務器驗證是否過時,是否有最新的版本;

  • must-revalidate:又是一個和 no_cache 類似的詞,它的意思是若是緩存不過時就能夠繼續使用,但過時了若是還想用就必須去服務器驗證。

對於後兩種驗證緩存的類型,HTTP採用條件請求字段,將緩存的判斷放在服務端進行處理,由此來避免兩次請求佔用網絡帶寬。

條件請求一共有 5 個頭字段,咱們最經常使用的是「if-Modified-Since」和「If-None-Match」這兩個。須要第一次的響應報文預先提供「Last-modified」和「ETag」,而後第二次請求時就能夠帶上緩存裏的原值,驗證資源是不是最新的。(看原文)

總結

  1. 緩存是優化系統性能的重要手段,HTTP 傳輸的每個環節中均可以有緩存;
  2. 服務器使用「Cache-Control」設置緩存策略,經常使用的是「max-age」,表示資源的有效期;
  3. 瀏覽器收到數據就會存入緩存,若是沒過時就能夠直接使用,過時就要去服務器驗證是否仍然可用;
  4. 驗證資源是否失效須要使用「條件請求」,經常使用的是「if-Modified-Since」和「If-None-Match」,收到 304 就能夠複用緩存裏的資源;
  5. 驗證資源是否被修改的條件有兩個:「Last-modified」和「ETag」,須要服務器預先在響應報文裏設置,搭配條件請求使用;
  6. 瀏覽器也能夠發送「Cache-Control」字段,使用「max-age=0」或「no_cache」刷新數據。

良心中間商:HTTP的代理服務

代理的主要做用:

  1. 負載均衡:將請求分發都不一樣後端服務機器。
  2. 健康檢查:使用「心跳」等機制監控後端服務器,發現有故障就及時「踢出」集羣,保證服務高可用;
  3. 安全防禦:保護被代理的後端服務器,限制 IP 地址或流量,抵禦網絡攻擊和過載;
  4. 加密卸載:對外網使用 SSL/TLS 加密通訊認證,而在安全的內網不加密,消除加解密成本;
  5. 數據過濾:攔截上下行的數據,任意指定策略修改請求或者響應;
  6. 內容緩存:暫存、複用服務器響應。

代理相關頭字段:

Via:標明代理的身份,追加代理用戶的主機名或者域名。

image-20200426140852819

X-Forwarded-For:每通過一個代理節點就會在字段裏追加一個信息。追加的是代理主機的IP。

X-Real-IP:記錄客戶端 IP 地址,沒有中間的代理信息,至關因而「X-Forwarded-For」的簡化版。

image-20200426141100741

從抓包裏就能夠清晰地看出代理與客戶端、源服務器的通訊過程:

  1. 客戶端 55061 先用三次握手鍊接到代理的 80 端口,而後發送 GET 請求;
  2. 代理不直接生產內容,因此就表明客戶端,用 55063 端口鏈接到源服務器,也是三次握手;
  3. 代理成功鏈接源服務器後,發出了一個 HTTP/1.0 的 GET 請求;
  4. 由於 HTTP/1.0 默認是短鏈接,因此源服務器發送響應報文後當即用四次揮手關閉鏈接;
  5. 代理拿到響應報文後再發回給客戶端,完成了一次代理服務。

總結:

  1. HTTP 代理就是客戶端和服務器通訊鏈路中的一箇中間環節,爲兩端提供「代理服務」;
  2. 代理處於中間層,爲 HTTP 處理增長了更多的靈活性,能夠實現負載均衡、安全防禦、數據過濾等功能;
  3. 代理服務器須要使用字段「Via」標記本身的身份,多個代理會造成一個列表;
  4. 若是想要知道客戶端的真實 IP 地址,可使用字段「X-Forwarded-For」和「X-Real-IP」;
  5. 專門的「代理協議」能夠在不改動原始報文的狀況下傳遞客戶端的真實 IP。

HTTP的緩存代理

這篇我的認爲是漲知識的一篇文章

總結

  1. 計算機領域裏最經常使用的性能優化手段是「時空轉換」,也就是「時間換空間」或者「空間換時間」,HTTP 緩存屬於後者;
  2. 緩存代理是增長了緩存功能的代理服務,緩存源服務器的數據,分發給下游的客戶端;
  3. 「Cache-Control」字段也能夠控制緩存代理,經常使用的有「private」「s-maxage」「no-transform」等,一樣必須配合「Last-modified」「ETag」等字段才能使用;
  4. 緩存代理有時候也會帶來負面影響,緩存不良數據,須要及時刷新或刪除。

安全篇

HTTPS是什麼?SSL/TLS又是什麼?

由於 HTTPS 至關於「HTTP+SSL/TLS+TCP/IP」,其中的「HTTP」和「TCP/IP」咱們都已經明白了,只要再瞭解一下 SSL/TLS,HTTPS 也就可以輕鬆掌握。

SSL 的全稱是「Secure Socket Layer」,由網景公司發明,當發展到 3.0 時被標準化,更名爲 TLS,即「Transport Layer Security」,但因爲歷史的緣由仍是有不少人稱之爲 SSL/TLS,或者直接簡稱爲 SSL。

SSL 使用了許多密碼學最早進的研究成果,綜合了對稱加密、非對稱加密、摘要算法、數字簽名、數字證書等技術,可以在不安全的環境中爲通訊的雙方建立出一個祕密的、安全的傳輸通道,爲 HTTP 套上一副堅固的盔甲。

由於HTTP明文傳輸的不安全因此在原先HTTP運行的TCP/IP層上面添加了一層TLS/SSL來確保安全性。

安全性主要包括如下四個方面

  • 機密性
  • 完整性
  • 身份認證
  • 不能否認

image-20200427140857905

SSL最初在1994年由網景公司提出,後在1999年更名爲TSL。目前普遍使用的協議是TSL1.2。

TLS 由記錄協議、握手協議、警告協議、變動密碼規範協議、擴展協議等幾個子協議組成,綜合使用了對稱加密、非對稱加密、身份認證等許多密碼學前沿技術。

TLS 的密碼套件命名很是規範,格式很固定。基本的形式是「密鑰交換算法 + 簽名算法 + 對稱加密算法 + 摘要算法」

image-20200427141242196

「握手時使用 ECDHE 算法進行密鑰交換,用 RSA 簽名和身份認證,握手後的通訊使用 AES 對稱算法,密鑰長度 256 位,分組模式是 GCM,摘要算法 SHA384 用於消息認證和產生隨機數。」

總結

  1. 由於 HTTP 是明文傳輸,因此不安全,容易被黑客竊聽或竄改;
  2. 通訊安全必須同時具有機密性、完整性,身份認證和不能否認這四個特性;
  3. HTTPS 的語法、語義仍然是 HTTP,但把下層的協議由 TCP/IP 換成了 SSL/TLS;
  4. SSL/TLS 是信息安全領域中的權威標準,採用多種先進的加密技術保證通訊安全;
  5. OpenSSL 是著名的開源密碼學工具包,是 SSL/TLS 的具體實現。

固若金湯的根本(上):對稱加密與非對稱加密

實現機密性最經常使用的手段是「加密」(encrypt),就是把消息用某種方式轉換成誰也看不懂的亂碼,只有掌握特殊「鑰匙」的人才能再轉換出原始文本。

這裏的「鑰匙」就叫作「密鑰」(key),加密前的消息叫「明文」(plain text/clear text),加密後的亂碼叫「密文」(cipher text),使用密鑰還原明文的過程叫「解密」(decrypt),是加密的反操做,加密解密的操做過程就是「加密算法」。

加密能夠分爲兩大類:對稱加密和非對稱加密

對稱加密

「對稱加密」很好理解,就是指加密和解密時使用的密鑰都是同一個,是「對稱」的。只要保證了密鑰的安全,那整個通訊過程就能夠說具備了機密性。

對稱加密的算法主要由AES以及ChaCha20 。

加密分組模式

對稱算法還有一個「分組模式」的概念,它可讓算法用固定長度的密鑰加密任意長度的明文,把小祕密(即密鑰)轉化爲大祕密(即密文)。

非對稱加密

對稱加密看上去好像完美地實現了機密性,但其中有一個很大的問題:如何把密鑰安全地傳遞給對方,術語叫「密鑰交換」。

非對稱加密的算法主要有RSA和ECC。

混合加密

因爲非對稱加密常用數學方法進行加密解密,因此計算時間較長。對稱加密時間則比非對稱加密速度快好幾個量級。因此TSL使用混合加密。

在通訊剛開始的時候使用非對稱算法,好比 RSA、ECDHE,首先解決密鑰交換的問題。

而後用隨機數產生對稱算法使用的「會話密鑰」(session key),再用公鑰加密。由於會話密鑰很短,一般只有 16 字節或 32 字節,因此慢一點也無所謂。

對方拿到密文後用私鑰解密,取出會話密鑰。這樣,雙方就實現了對稱密鑰的安全交換,後續就再也不使用非對稱加密,全都使用對稱加密。

image-20200427143640443

總結

  1. 加密算法的核心思想是「把一個小祕密(密鑰)轉化爲一個大祕密(密文消息)」,守住了小祕密,也就守住了大祕密;
  2. 對稱加密只使用一個密鑰,運算速度快,密鑰必須保密,沒法作到安全的密鑰交換,經常使用的有 AES 和 ChaCha20;
  3. 非對稱加密使用兩個密鑰:公鑰和私鑰,公鑰能夠任意分發而私鑰保密,解決了密鑰交換問題但速度慢,經常使用的有 RSA 和 ECC;
  4. 把對稱加密和非對稱加密結合起來就獲得了「又好又快」的混合加密,也就是 TLS 裏使用的加密方式。

固若金湯的根本(下):數字簽名與證書

實現完整性的手段主要是摘要算法(Digest Algorithm),也就是常說的散列函數、哈希函數(Hash Function)。

摘要算法使得絲絕不同的內容產生的結果也是徹底不一樣,TLS推薦使用的摘要算法主要是 SHA-2MD5以及SHA-1因爲算法的安全性不足 ,在TLS中被禁用。

真正的完整性必需要創建在機密性之上,在混合加密系統裏用會話密鑰加密消息和摘要,這樣黑客沒法得知明文,也就沒有辦法動手腳了。

image-20200427145952129

數字簽名

image-20200427175035683

非對稱加密裏的「私鑰」,使用私鑰再加上摘要算法,就可以實現「數字簽名」,同時實現「身份認證」和「不能否認」。

數字簽名的原理其實很簡單,就是把公鑰私鑰的用法反過來,以前是公鑰加密、私鑰解密,如今是私鑰加密、公鑰解密。

但又由於非對稱加密效率過低,因此私鑰只加密原文的摘要,這樣運算量就小的多,並且獲得的數字簽名也很小,方便保管和傳輸。

簽名和公鑰同樣徹底公開,任何人均可以獲取。但這個簽名只有用私鑰對應的公鑰才能解開,拿到摘要後,再比對原文驗證完整性,就能夠像簽署文件同樣證實消息確實是你發的。

數字證書和 CA

咱們常說的CA(Certificate Authority,證書認證機構)。它就像網絡世界裏的公安局、教育部、公證中心,具備極高的可信度,由它來給各個公鑰簽名,用自身的信譽來保證公鑰沒法僞造,是可信的。

CA 對公鑰的簽名認證也是有格式的,不是簡單地把公鑰綁定在持有者身份上就完事了,還要包含序列號、用途、頒發者、有效時間等等,把這些打成一個包再簽名,完整地證實公鑰關聯的各類信息,造成「數字證書」(Certificate)。

總結

  1. 摘要算法用來實現完整性,可以爲數據生成獨一無二的「指紋」,經常使用的算法是 SHA-2;
  2. 數字簽名是私鑰對摘要的加密,能夠由公鑰解密後驗證,實現身份認證和不能否認;
  3. 公鑰的分發須要使用數字證書,必須由 CA 的信任鏈來驗證,不然就是不可信的;
  4. 做爲信任鏈的源頭 CA 有時也會不可信,解決辦法有 CRL、OCSP,還有終止信任。

飛翔篇

時代之風(上):HTTP/2特性概覽

頭部壓縮

因爲報文請求頭通常都會攜帶許多固定的頭字段,而請求體的內容每每只有不多同時屢次重複的請求使得重複的頭部字段被屢次發送,因此HTTP2開發出專門的壓縮算法進行頭部壓縮,因爲gzip算法會被」crime「攻擊因此HTTP2開發了專門的「HPACK」算法,在客戶端和服務器兩端創建「字典」,用索引號表示重複的字符串,還釆用哈夫曼編碼來壓縮整數和字符串,能夠達到 50%~90% 的高壓縮率。

二進制格式

因爲傳統的純文本形式會使用複雜的狀態機,致使文本解析效率低。HTTP2採用二進制來優化,將原來的的「Header+Body」的消息「打散」爲數個小片的二進制「幀」(Frame),用「HEADERS」幀存放頭數據、「DATA」幀存放實體數據。

image-20200427181222491

虛擬的「流」

HTTP/2 爲此定義了一個「」(Stream)的概念,它是二進制幀的雙向傳輸序列,同一個消息往返的幀會分配一個惟一的流 ID。經過流ID來組裝分散的二進制幀,由於「流」是虛擬的,實際上並不存在,因此 HTTP/2 就能夠在一個 TCP 鏈接上用「」同時發送多個「碎片化」的消息,這就是常說的「多路複用」( Multiplexing)——多個往返通訊都複用一個鏈接來處理。

推送模式

HTTP/2 還在必定程度上改變了傳統的「請求 - 應答」工做模式,服務器再也不是徹底被動地響應請求,也能夠新建「流」主動向客戶端發送消息。好比,在瀏覽器剛請求 HTML 的時候就提早把可能會用到的 JS、CSS 文件發給客戶端,減小等待的延遲,這被稱爲「服務器推送」(Server Push,也叫 Cache Push)。

強化安全

互聯網上一般所能見到的 HTTP/2 都是使用「https」協議名,跑在 TLS 上面。

爲了區分「加密」和「明文」這兩個不一樣的版本,HTTP/2 協議定義了兩個字符串標識符:「h2」表示加密的HTTP/2,「h2c」表示明文的 HTTP/2,多出的那個字母「c」的意思是「clear text」。

協議棧

image-20200427182025345

小結:

  1. HTTP 協議取消了小版本號,因此 HTTP/2 的正式名字不是 2.0;
  2. HTTP/2 在「語義」上兼容 HTTP/1,保留了請求方法、URI 等傳統概念;
  3. HTTP/2 使用「HPACK」算法壓縮頭部信息,消除冗餘數據節約帶寬;
  4. HTTP/2 的消息再也不是「Header+Body」的形式,而是分散爲多個二進制「幀」;
  5. HTTP/2 使用虛擬的「流」傳輸消息,解決了困擾多年的「隊頭阻塞」問題,同時實現了「多路複用」,提升鏈接的利用率;
  6. HTTP/2 也加強了安全性,要求至少是 TLS1.2,並且禁用了不少不安全的密碼套件。

時代之風(下):HTTP/2內核剖析(乾貨)

鏈接前言

TLS 握手成功以後,客戶端必需要發送一個「鏈接前言」(connection preface),用來確認創建 HTTP/2 鏈接。

HTTP2的鏈接前言使用的是「Magic」確保使用的HTTP2

頭部壓縮 :smiling_imp:

頭部壓縮算法使用的是HPACK算法。它是一個「有狀態」的算法,須要客戶端和服務器各自維護一份「索引表」,也能夠說是「字典」(這有點相似 brotli),壓縮和解壓縮就是查表和更新表的操做。 具體的實現爲將原先頭部的字段改成僞頭部形式爲「:authority」,":method"等來跟原先頭部進行區分。HTTP/2 就爲一些最經常使用的頭字段定義了一個只讀的「靜態表」(Static Table)。經過key——value的形式如 ":method":2來表示GET請求,在發送時候只要一個字節發送對應的索引2就能夠。

image-20200428135524654

同時爲了解決自定義字段找不到的問題,使用了動態表,跟在靜態表的後面,在編碼解碼的時候隨時更新。

image-20200428135614596

二進制幀

格式

image-20200428140249095

二進制幀頭部佔9個字節。 幀長度3個字節表示最大傳輸的大小爲2^24 爲16M,通常默認上限爲2^14 爲16Kb 幀類型,大體能夠分紅數據幀控制幀兩類,HEADERS 幀和 DATA 幀屬於數據幀,存放的是 HTTP 報文,而 SETTINGS、PING、PRIORITY 等則是用來管理流的控制幀。

標誌位:能夠保存 8 個標誌,攜帶簡單的控制信息。經常使用的標誌位有END_HEADERS表示頭數據結束,至關於 HTTP/1 裏頭後的空行(「\r\n」),END_STREAM表示單方向數據發送結束(即 EOS,End of Stream),至關於 HTTP/1 裏 Chunked 分塊結束標誌(「0\r\n\r\n」)。

流標識符:是用來確保多個複用的一個重要標誌,接收方使用它就能夠從亂序的幀裏識別出具備相同流 ID 的幀序列,按順序組裝起來就實現了虛擬的「流」。擁有32位,最多能夠表示21億個標誌,不過通常發送端使用的單數,服務端使用雙數。單邊流標誌在10億個左右。

流與多路複用

流是二進制幀的雙向傳輸序列 **在 HTTP/2 鏈接上,雖然幀是亂序收發的,但只要它們都擁有相同的流 ID,就都屬於一個流,並且在這個流裏幀不是無序的,而是有着嚴格的前後順序。**http2解決了原先請求響應的隊頭阻塞問題,須要明白的是並無解決流內部的隊頭阻塞問題,由於HTTP2使用的還是TCP協議,HTTP3改變使用UDP。

流的特色:

  1. 流是可併發的,一個 HTTP/2 鏈接上能夠同時發出多個流傳輸數據,也就是併發多請求,實現「多路複用」;
  2. 客戶端和服務器均可以建立流,雙方互不干擾;
  3. 流是雙向的,一個流裏面客戶端和服務器均可以發送或接收數據幀,也就是一個「請求 - 應答」來回;
  4. 流之間沒有固定關係,彼此獨立,但流內部的幀是有嚴格順序的;
  5. 流能夠設置優先級,讓服務器優先處理,好比先傳 HTML/CSS,後傳圖片,優化用戶體驗;
  6. 流 ID 不能重用,只能順序遞增,客戶端發起的 ID 是奇數,服務器端發起的 ID 是偶數;
  7. 在流上發送「RST_STREAM」幀能夠隨時終止流,取消接收或發送;
  8. 第 0 號流比較特殊,不能關閉,也不能發送數據幀,只能發送控制幀,用於流量控制。

image-20200428142358384

流狀態轉換

狀態轉換相似tcp的狀態轉換

image-20200428142827628

總結:

  1. HTTP/2 必須先發送一個「鏈接前言」字符串,而後才能創建正式鏈接;
  2. HTTP/2 廢除了起始行,統一使用頭字段,在兩端維護字段「Key-Value」的索引表,使用「HPACK」算法壓縮頭部;
  3. HTTP/2 把報文切分爲多種類型的二進制幀,報頭裏最重要的字段是流標識符,標記幀屬於哪一個流;
  4. 流是 HTTP/2 虛擬的概念,是幀的雙向傳輸序列,至關於 HTTP/1 裏的一次「請求 - 應答」;
  5. 在一個 HTTP/2 鏈接上能夠併發多個流,也就是多個「請求 - 響應」報文,這就是「多路複用」。

總結篇 探索篇 安全篇的部份內容沒有記錄 本身感受在實踐中沒有太多用到,或者是自身儲備不足。下次再作記錄。

相關文章
相關標籤/搜索