目錄
1. HTTP原理
2. HTTP請求報文
3. HTTP響應報文
4. HTTP緩存(瀏覽器緩存機制)
5. 不同版本HTTP
(一)HTTP原理
這部分學習並參考於:HTTP協議超級詳解
超文本傳輸協議(英文:HyperText Transfer Protocol,縮寫:HTTP)是一種用於分佈式、協作式和超媒體信息系統的應用層協議。HTTP是萬維網的數據通信的基礎。
HTTP是一個客戶端終端(用戶)和服務器端(網站)請求和應答的標準(TCP)。
http協議是基於TCP/IP協議之上的應用層協議。
1. HTTP 請求/響應的步驟:
HTTP協議採用了請求/響應模型。客戶端向服務器發送一個請求報文,請求報文包含請求行(請求的方法、URL、協議版本)、請求頭部和請求數據。服務器以一個狀態行作爲響應,響應的內容包括響應行(協議的版本、狀態碼、狀態信息)、響應頭部和響應數據。
-
客戶端連接到Web服務器
一個HTTP客戶端,通常是瀏覽器,與Web服務器的HTTP端口(默認爲80)建立一個TCP套接字連接。
-
發送HTTP請求
通過TCP套接字,客戶端向Web服務器發送一個文本的請求報文,一個請求報文由請求行、請求頭部、空行和請求數據4部分組成。
-
服務器接受請求並返回HTTP響應
Web服務器解析請求,定位請求資源。服務器將資源複本寫到TCP套接字,由客戶端讀取。一個響應由狀態行、響應頭部、空行和響應數據4部分組成。
-
釋放連接TCP連接
若connection 模式爲close,則服務器主動關閉TCP連接,客戶端被動關閉連接,釋放TCP連接;若connection 模式爲keepalive,則該連接會保持一段時間,在該時間內可以繼續接收請求;
-
客戶端瀏覽器解析HTML內容
2. HTTP特點:
-
基於TCP/IP協議之上的應用層協議。
-
基於 請求-響應 的模式
HTTP協議規定,請求從客戶端發出,最後服務器端響應該請求並 返回。換句話說,肯定是先從客戶端開始建立通信的,服務器端在沒有 接收到請求之前不會發送響應
-
無狀態保存
HTTP是一種不保存狀態,即無狀態(stateless)協議。HTTP協議 自身不對請求和響應之間的通信狀態進行保存。也就是說在HTTP這個 級別,協議對於發送過的請求或響應都不做持久化處理。協議本身並不保留之前一切的請求或響應報文的信息。這是爲了更快地處理大量事務,確保協議的可伸縮性,而特意把HTTP協議設計成 如此簡單的。
-
無連接
無連接的含義是限制每次連接只處理一個請求。服務器處理完客戶的請求,並收到客戶的應答後,即斷開連接。採用這種方式可以節省傳輸時間,並且可以提高併發性能,不能和每個用戶建立長久的連接,請求一次相應一次,服務端和客戶端就中斷了。
但是無連接有兩種方式,早期的http協議是一個請求一個響應之後,直接就斷開了,但是現在的http協議1.1版本不是直接就斷開了,而是等幾秒鐘,這幾秒鐘是等什麼呢,等着用戶有後續的操作,如果用戶在這幾秒鐘之內有新的請求,那麼還是通過之前的連接通道來收發消息,如果過了這幾秒鐘用戶沒有發送新的請求,那麼就會斷開連接,這樣可以提高效率,減少短時間內建立連接的次數,因爲建立連接也是耗時的,默認的好像是3秒中現在,但是這個時間是可以通過咱們後端的代碼來調整的,自己網站根據自己網站用戶的行爲來分析統計出一個最優的等待時間。
(二)HTTP請求報文
1. 請求報文結構
請求報文由請求行(請求方法、URL、協議版本)、請求頭部和請求體(請求數據)組成。
下面是一個實際的請求報文:
下面分別展開說明請求行、請求頭、請求體。
2. 請求行
請求行由三部分組成:請求方法,請求URL(不包括域名),HTTP協議版本
(1)請求方法:
請求方法比較多:GET、POST、HEAD、PUT、DELETE、OPTIONS、TRACE、CONNECT
其中:
- HTTP1.0定義了三種請求方法: GET, POST 和 HEAD方法。
- HTTP1.1新增了五種請求方法:OPTIONS, PUT, DELETE, TRACE 和 CONNECT 方法。
方法 | 描述 |
---|---|
GET | 從指定的資源請求數據 |
HEAD | 向服務器請求與GET請求相一致的響應,只不過響應體將不會被返回。這一方法可以再不必傳輸整個響應內容的情況下,就可以獲取包含在響應小消息頭中的元信息。 |
POST | 向指定的資源提交要被處理的數據(例如提交表單或者上傳文件) |
PUT | 向指定資源位置上傳其最新內容 |
DELETE | 請求服務器刪除Request-URL所標識的資源 |
CONNECT | HTTP/1.1協議中預留給能夠將連接改爲管道方式的代理服務器。 |
OPTIONS | 用於請求獲得由Request-URI標識的資源在請求/響應的通信過程中可以使用的功能選項。允許客戶端查看服務器的性能。 |
TRACE | 回顯服務器收到的請求,主要用於測試或診斷 |
注意:
- 方法名稱是區分大小寫的。當某個請求所針對的資源不支持對應的請求方法的時候,服務器應當返回狀態碼405(Method Not Allowed),當服務器不認識或者不支持對應的請求方法的時候,應當返回狀態碼501(Not Implemented)。
- HTTP服務器至少應該實現GET和HEAD方法,其他方法都是可選的。當然,所有的方法支持的實現都應當匹配下述的方法各自的語義定義。此外,除了上述方法,特定的HTTP服務器還能夠擴展自定義的方法。例如PATCH(由 RFC 5789 指定的方法)用於將局部修改應用到資源*。*
關於請求方法的常見面試題
-
HEAD
HEAD方法跟GET方法相同,只不過服務器響應時不會返回消息體。一個HEAD請求的響應中,HTTP頭中包含的元信息應該和一個GET請求的響應消息相同。這種方法可以用來獲取請求中隱含的元信息,而不用傳輸實體本身。也經常用來測試超鏈接的有效性、可用性和最近的修改。
HEAD請求主要有以下特點:
- 只請求資源的首部;
- 檢查超鏈接的有效性;
- 檢查網頁是否被修改;
- 多用於自動搜索機器人獲取網頁的標誌信息,獲取rss種子信息,或者傳遞安全認證信息等
-
get和post的區別
-
傳參方式
get傳參方式是通過地址欄URL傳遞,get把請求的數據在URL後通過?連接,通過&進行參數分割。是可以直接在url中看到get傳遞的參數。
post傳參方式是將從參數存放在HTTP的包體內,在url看不到它傳遞的參數。
-
傳輸數據大小
get傳遞數據是通過URL進行傳遞,對傳遞的數據長度是受到URL大小的限制,URL最大長度是2048個字符。post沒有長度限制。
-
編碼方式
get請求只URL編碼,post支持多種編碼方式
-
字符類型
get只支持ASCII字符,post沒有字符類型限制
-
歷史記錄
get請求的記錄會留在歷史記錄中,post請求不會留在歷史記錄
-
緩存
get請求可以被緩存,post不可以被緩存
get請求類似於查找的過程,用戶獲取數據,可以不用每次都與數據庫連接,所以可以使用緩存。post不同,post做的一般是修改和刪除的工作,所以必須與數據庫交互,所以不能使用緩存。因此get請求適合於請求緩存。
-
GET和POST的底層也是TCP/IP,GET/POST都是TCP鏈接。
而GET產生一個TCP數據包;POST產生兩個TCP數據包。
-
對於GET方式的請求,瀏覽器會把http header和data一併發送出去,服務器響應200(返回數據);而對於POST,瀏覽器先發送header,服務器響應100 continue,瀏覽器再發送data,服務器響應200 ok(返回數據)。
-
終極區別:冪等性區別
冪等性是指一次和多次請求某一個資源應該具有同樣的副作用。簡單來說意味着對同一URL的多個請求應該返回同樣的結果。
GET和POST最大的區別主要是GET請求是冪等性的,POST請求不是。
-
-
options
(2)請求URL
這部分學習並摘自:統一資源定位符URL和統一資源標識符URI
先說說URI(Uniform Resource Identifiers):統一資源標識符。
HTTP使用統一資源標識符來傳輸數據和建立連接。URL是一種特殊類型的URI,包含用於查找某個資源的足夠信息。
URL(Uniform Resource Locator):統一資源定位符。是互聯網上用來標識某一處資源的地址。
以下URL爲例子做介紹:
http://www.aspxfans.com:8080/news/index.asp?boardID=5&ID=24618&page=1#name
從上面的URL看出,一個完整的URL包含這7部分:
- 協議部分:“http:”這裏使用HTTP協議,協議後面的“//”爲分隔符
- 域名部分:“www.aspxfans.com”,URL中也可以使用IP地址作爲域名
- 端口部分(非必要):“8080”,在域名之後,使用“:”作爲分隔符,若省略端口則會採用默認端口
- 虛擬目錄部分(非必要):“/news/”域名後的第一個“/”到最後一個“/”中間是虛擬目錄部分
- 文件名部分(非必要):“index.asp”,從域名後的最後一個“/”到“?”之間是文件名部分;如果沒有“?”,那就是從域名後的最後一個“/”到“#”是文件名部分
- 錨部分(非必要):“name”,從“#”到最後都是錨部分
- 參數部分:也叫搜索部分、查詢部分,“boardID=5&ID=24618&page=1”,從“?”到“#”之間是參數部分,可有多個參數,參數之間用“&”作爲分隔符
(3)HTTP協議版本
HTTP版本協議主要有HTTP1.0、HTTP1.1、HTTP2.0。
筆者在文章下面會有一部分專門寫這幾個版本以及HTTPS的區別,這裏先不多寫。
3. HTTP請求頭
HTTP請求頭提供了關於請求,響應或者其他的發送實體的信息。
Header | 解釋 | 示例 |
---|---|---|
Accept | 指定客戶端能夠接受的響應內容類型 | Accept: text/plain, text/html |
Accept-Charset | 瀏覽器可以接受的字符編碼集。 | Accept-Charset: iso-8859-5 |
Accept-Encoding | 指定瀏覽器可以支持的web服務器返回內容壓縮編碼類型。 | Accept-Encoding: compress, gzip |
Accept-Language | 瀏覽器可接受的語言 | Accept-Language: en,zh |
Accept-Ranges | 可以請求網頁實體的一個或者多個子範圍字段 | Accept-Ranges: bytes |
Authorization | HTTP授權的授權證書 | Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ== |
Cache-Control | 指定請求和響應遵循的緩存機制 | Cache-Control: no-cache |
Connection | 表示是否需要持久連接。(HTTP 1.1默認進行持久連接) | Connection: close |
Cookie | HTTP請求發送時,會把保存在該請求域名下的所有cookie值一起發送給web服務器。 | Cookie: $Version=1; Skin=new; |
Content-Length | 請求的內容長度 | Content-Length: 348 |
Content-Type | 請求的與實體對應的MIME信息 | Content-Type: application/x-www-form-urlencoded |
Date | 請求發送的日期和時間 | Date: Tue, 15 Nov 2010 08:12:31 GMT |
Expect | 請求的特定的服務器行爲 | Expect: 100-continue |
From | 發出請求的用戶的Email | From: [email protected] |
Host | 指定請求的服務器的域名和端口號 | Host: www.zcmhi.com |
If-Match | 只有請求內容與實體相匹配纔有效 | If-Match: “737060cd8c284d8af7ad3082f209582d” |
If-Modified-Since | 如果請求的部分在指定時間之後被修改則請求成功,未被修改則返回304代碼 | If-Modified-Since: Sat, 29 Oct 2010 19:43:31 GMT |
If-None-Match | 如果內容未改變返回304代碼,參數爲服務器先前發送的Etag,與服務器迴應的Etag比較判斷是否改變 | If-None-Match: “737060cd8c284d8af7ad3082f209582d” |
If-Range | 如果實體未改變,服務器發送客戶端丟失的部分,否則發送整個實體。參數也爲Etag | If-Range: “737060cd8c284d8af7ad3082f209582d” |
If-Unmodified-Since | 只在實體在指定時間之後未被修改才請求成功 | If-Unmodified-Since: Sat, 29 Oct 2010 19:43:31 GMT |
Max-Forwards | 限制信息通過代理和網關傳送的時間 | Max-Forwards: 10 |
Pragma | 用來包含實現特定的指令 | Pragma: no-cache |
Proxy-Authorization | 連接到代理的授權證書 | Proxy-Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ== |
Range | 只請求實體的一部分,指定範圍 | Range: bytes=500-999 |
Referer | 先前網頁的地址,當前請求網頁緊隨其後,即來路 | Referer: http://www.zcmhi.com/archives/71.html |
TE | 客戶端願意接受的傳輸編碼,並通知服務器接受接受尾加頭信息 | TE: trailers,deflate;q=0.5 |
Upgrade | 向服務器指定某種傳輸協議以便服務器進行轉換(如果支持) | Upgrade: HTTP/2.0, SHTTP/1.3, IRC/6.9, RTA/x11 |
User-Agent | User-Agent的內容包含發出請求的用戶信息 | User-Agent: Mozilla/5.0 (Linux; X11) |
Via | 通知中間網關或代理服務器地址,通信協議 | Via: 1.0 fred, 1.1 nowhere.com (Apache/1.1) |
Warning | 關於消息實體的警告信息 | Warn: 199 Miscellaneous warning |
(三)HTTP響應報文
1. 響應報文結構概述
響應報文 由響應行(版本協議、狀態碼及其狀態描述)、響應頭、響應體組成。
下面是一個實際的響應報文:
2. 響應行
響應行由三部分組成:版本協議、狀態碼、狀態碼描述。
(1)狀態碼
狀態代碼的第一個數字代表當前響應的類型:
狀態碼 | 狀態碼英文名稱 | 中文描述 |
---|---|---|
100 | Continue | 繼續。客戶端應繼續其請求 |
101 | Switching Protocols | 切換協議。服務器根據客戶端的請求切換協議。只能切換到更高級的協議,例如,切換到HTTP的新版本協議 |
200 | OK | 請求成功。一般用於GET與POST請求 |
201 | Created | 已創建。成功請求並創建了新的資源 |
202 | Accepted | 已接受。已經接受請求,但未處理完成 |
203 | Non-Authoritative Information | 非授權信息。請求成功。但返回的meta信息不在原始的服務器,而是一個副本 |
204 | No Content | 無內容。服務器成功處理,但未返回內容。在未更新網頁的情況下,可確保瀏覽器繼續顯示當前文檔 |
205 | Reset Content | 重置內容。服務器處理成功,用戶終端(例如:瀏覽器)應重置文檔視圖。可通過此返回碼清除瀏覽器的表單域 |
206 | Partial Content | 部分內容。服務器成功處理了部分GET請求 |
300 | Multiple Choices | 多種選擇。請求的資源可包括多個位置,相應可返回一個資源特徵與地址的列表用於用戶終端(例如:瀏覽器)選擇 |
301 | Moved Permanently | 永久移動。請求的資源已被永久的移動到新URI,返回信息會包括新的URI,瀏覽器會自動定向到新URI。今後任何新的請求都應使用新的URI代替 |
302 | Found | 臨時移動。與301類似。但資源只是臨時被移動。客戶端應繼續使用原有URI |
303 | See Other | 查看其它地址。與301類似。使用GET和POST請求查看 |
304 | Not Modified | 未修改。所請求的資源未修改,服務器返回此狀態碼時,不會返回任何資源。客戶端通常會緩存訪問過的資源,通過提供一個頭信息指出客戶端希望只返回在指定日期之後修改的資源 |
305 | Use Proxy | 使用代理。所請求的資源必須通過代理訪問 |
306 | Unused | 已經被廢棄的HTTP狀態碼 |
307 | Temporary Redirect | 臨時重定向。與302類似。使用GET請求重定向 |
400 | Bad Request | 客戶端請求的語法錯誤,服務器無法理解 |
401 | Unauthorized | 請求要求用戶的身份認證 |
402 | Payment Required | 保留,將來使用 |
403 | Forbidden | 服務器理解請求客戶端的請求,但是拒絕執行此請求 |
404 | Not Found | 服務器無法根據客戶端的請求找到資源(網頁)。通過此代碼,網站設計人員可設置"您所請求的資源無法找到"的個性頁面 |
405 | Method Not Allowed | 客戶端請求中的方法被禁止 |
406 | Not Acceptable | 服務器無法根據客戶端請求的內容特性完成請求 |
407 | Proxy Authentication Required | 請求要求代理的身份認證,與401類似,但請求者應當使用代理進行授權 |
408 | Request Time-out | 服務器等待客戶端發送的請求時間過長,超時 |
409 | Conflict | 服務器完成客戶端的PUT請求是可能返回此代碼,服務器處理請求時發生了衝突 |
410 | Gone | 客戶端請求的資源已經不存在。410不同於404,如果資源以前有現在被永久刪除了可使用410代碼,網站設計人員可通過301代碼指定資源的新位置 |
411 | Length Required | 服務器無法處理客戶端發送的不帶Content-Length的請求信息 |
412 | Precondition Failed | 客戶端請求信息的先決條件錯誤 |
413 | Request Entity Too Large | 由於請求的實體過大,服務器無法處理,因此拒絕請求。爲防止客戶端的連續請求,服務器可能會關閉連接。如果只是服務器暫時無法處理,則會包含一個Retry-After的響應信息 |
414 | Request-URI Too Large | 請求的URI過長(URI通常爲網址),服務器無法處理 |
415 | Unsupported Media Type | 服務器無法處理請求附帶的媒體格式 |
416 | Requested range not satisfiable | 客戶端請求的範圍無效 |
417 | Expectation Failed | 服務器無法滿足Expect的請求頭信息 |
500 | Internal Server Error | 服務器內部錯誤,無法完成請求 |
501 | Not Implemented | 服務器不支持請求的功能,無法完成請求 |
502 | Bad Gateway | 充當網關或代理的服務器,從遠端服務器接收到了一個無效的請求 |
503 | Service Unavailable | 由於超載或系統維護,服務器暫時的無法處理客戶端的請求。延時的長度可包含在服務器的Retry-After頭信息中 |
504 | Gateway Time-out | 充當網關或代理的服務器,未及時從遠端服務器獲取請求 |
505 | HTTP Version not supported | 服務器不支持請求的HTTP協議的版本,無法完成處理 |
具體查看:HTTP狀態碼對照表
(2)關於狀態碼的常見面試題
-
301和302有什麼具體區別
301:永久移動,請求的網頁已永久移動到新的位置,服務器返回此響應,會自動將請求者轉到新位置
302:臨時移動,服務器目前從不同位置的網頁響應請求,但請求者應繼續使用原有位置來繼續以後的請求。
-
200和304 的區別
200表示成功,服務器已成功處理了請求,通常表示爲服務器提供了請求的網頁
304表示未修改,自從上次請求後,請求的網頁未修改過,服務器返回此響應時不會返回網頁內容。
-
400和401、403狀態碼
400狀態碼:請求無效
產生原因:前端提交數據的字段名稱和字段類型與後臺的實體沒有保持一致
前端提交到後臺的數據應該是json字符串類型,但是前端沒有將對象JSON.stringify轉化成字符串。
解決方法:對照字段的名稱,保持一致性,將obj對象通過JSON.stringify實現序列化
401狀態碼:當前請求需要用戶驗證
403狀態碼:服務器已經得到請求,但是拒絕執行
3. 響應頭
Header | 解釋 | 示例 |
---|---|---|
Accept-Ranges | 表明服務器是否支持指定範圍請求及哪種類型的分段請求 | Accept-Ranges: bytes |
Age | 從原始服務器到代理緩存形成的估算時間(以秒計,非負) | Age: 12 |
Allow | 對某網絡資源的有效的請求行爲,不允許則返回405 | Allow: GET, HEAD |
Cache-Control | 告訴所有的緩存機制是否可以緩存及哪種類型 | Cache-Control: no-cache |
Content-Encoding | web服務器支持的返回內容壓縮編碼類型。 | Content-Encoding: gzip |
Content-Language | 響應體的語言 | Content-Language: en,zh |
Content-Length | 響應體的長度 | Content-Length: 348 |
Content-Location | 請求資源可替代的備用的另一地址 | Content-Location: /index.htm |
Content-MD5 | 返回資源的MD5校驗值 | Content-MD5: Q2hlY2sgSW50ZWdyaXR5IQ== |
Content-Range | 在整個返回體中本部分的字節位置 | Content-Range: bytes 21010-47021/47022 |
Content-Type | 返回內容的MIME類型 | Content-Type: text/html; charset=utf-8 |
Date | 原始服務器消息發出的時間 | Date: Tue, 15 Nov 2010 08:12:31 GMT |
ETag | 請求變量的實體標籤的當前值 | ETag: “737060cd8c284d8af7ad3082f209582d” |
Expires | 響應過期的日期和時間 | Expires: Thu, 01 Dec 2010 16:00:00 GMT |
Last-Modified | 請求資源的最後修改時間 | Last-Modified: Tue, 15 Nov 2010 12:45:26 GMT |
Location | 用來重定向接收方到非請求URL的位置來完成請求或標識新的資源 | Location: http://www.zcmhi.com/archives/94.html |
Pragma | 包括實現特定的指令,它可應用到響應鏈上的任何接收方 | Pragma: no-cache |
Proxy-Authenticate | 它指出認證方案和可應用到代理的該URL上的參數 | Proxy-Authenticate: Basic |
refresh | 應用於重定向或一個新的資源被創造,在5秒之後重定向(由網景提出,被大部分瀏覽器支持) | Refresh: 5; url=http://www.zcmhi.com/archives/94.html |
Retry-After | 如果實體暫時不可取,通知客戶端在指定時間之後再次嘗試 | Retry-After: 120 |
Server | web服務器軟件名稱 | Server: Apache/1.3.27 (Unix) (Red-Hat/Linux) |
Set-Cookie | 設置Http Cookie | Set-Cookie: UserID=JohnDoe; Max-Age=3600; Version=1 |
Trailer | 指出頭域在分塊傳輸編碼的尾部存在 | Trailer: Max-Forwards |
Transfer-Encoding | 文件傳輸編碼 | Transfer-Encoding:chunked |
Vary | 告訴下游代理是使用緩存響應還是從原始服務器請求 | Vary: * |
Via | 告知代理客戶端響應是通過哪裏發送的 | Via: 1.0 fred, 1.1 nowhere.com (Apache/1.1) |
Warning | 警告實體可能存在的問題 | Warning: 199 Miscellaneous warning |
WWW-Authenticate | 表明客戶端請求實體應該使用的授權方案 | WWW-Authenticate: Basic |
(四)HTTP緩存
筆者只看學習HTTP緩存時閱讀了下面這篇博文,覺得寫得很贊,推薦閱讀。第二篇主要是一些概念,可補充閱讀。
(五)不同版本HTTP
1. HTTP 0.9
HTTP 0.9是第一個版本的HTTP協議,已過時。它的組成極其簡單,只允許客戶端發送GET這一種請求,且不支持請求頭。由於沒有協議頭,造成了HTTP 0.9協議只支持一種內容,即純文本。不過網頁仍然支持用HTML語言格式化,同時無法插入圖片。
HTTP 0.9具有典型的無狀態性,每個事務獨立進行處理,事務結束時就釋放這個連接。由此可見,HTTP協議的無狀態特點在其第一個版本0.9中已經成型。一次HTTP 0.9的傳輸首先要建立一個由客戶端到Web服務器的TCP連接,由客戶端發起一個請求,然後由Web服務器返回頁面內容,然後連接會關閉。如果請求的頁面不存在,也不會返回任何錯誤碼。
2. HTTP 1.0
HTTP協議的第二個版本,第一個在通訊中指定版本號的HTTP協議版本,至今仍被廣泛採用。相對於HTTP 0.9 增加了如下主要特性:
- 請求與響應支持頭域
- 響應對象以一個響應狀態行開始
- 響應內容不只限於超文本
- 開始支持客戶端通過POST方法向Web服務器提交數據,支持GET、HEAD、POST方法
- 支持長連接(默認還是使用短連接),使用長連接需要添加請求頭 Connection: Keep-Alive,緩存機制,以及身份認證
3. HTTP 1.1
HTTP協議的第三個版本是HTTP 1.1,是目前使用最廣泛的協議版本 。
HTTP 1.1引入了許多關鍵性能優化:
-
持久連接(Persistent Connections)
也就是
Connection:keep-alive
,服務器返回請求之後不會立刻關閉連接,允許客戶端使用同一個連接發送後續HTTP請求。這在HTTP/1.1
是默認開啓的,除非指定Connection: close
首部。好處是,使網頁響應更快。但是對於訪問量大的服務器來說,他要維持更多連接會有更大的開銷,所以會關掉,比如大型電商網站。
-
HTTP 管道(Pipelining)
客戶端把多個HTTP請求放到一個TCP連接中一一發送,而在發送過程中不需要等待服務器對前一個請求的響應。增加了併發性,進一步改善了HTTP協議的效率。
舉例來說,客戶端需要請求兩個資源。以前的做法是,在同一個TCP連接裏面,先發送A請求,然後等待服務器做出迴應,收到後再發出B請求。管道機制則是允許瀏覽器同時發出A請求和B請求,但是服務器還是按照順序請求的,先回應A請求,完成後再回應B請求。如果前一個請求非常耗時,後續的請求都會受影響,在客戶端這裏導致一個隊首阻塞的問題,所以現代瀏覽器都關閉這個功能。
-
Content-Length 字段
一個TCP連接現在可以傳送多個迴應,勢必就要有一種機制,區分數據包是屬於哪一個迴應的。這就是
Content-length
字段的作用,聲明本次迴應的數據長度。Content-Length: 3495
上面代碼告訴瀏覽器,本次迴應的長度是3495個字節,後面的字節就屬於下一個迴應了。
在1.0版中,
Content-Length
字段不是必需的,因爲瀏覽器發現服務器關閉了TCP連接,就表明收到的數據包已經全了。 -
Chunked 編碼(Chunked Encoding)
使用
Content-Length
字段的前提條件是,服務器發送迴應之前,必須知道迴應的數據長度。對於一些很耗時的動態操作來說,這意味着,服務器要等到所有操作完成,才能發送數據,顯然這樣的效率不高。更好的處理方法是,產生一塊數據,就發送一塊,採用"流模式"(stream)取代"緩存模式"(buffer)。
因此,1.1版規定可以不使用
Content-Length
字段,而使用"分塊傳輸編碼"(chunked transfer encoding)。只要請求或迴應的頭信息有Transfer-Encoding
字段,就表明迴應將由數量未定的數據塊組成。Transfer-Encoding: chunked
每個非空的數據塊之前,會有一個16進制的數值,表示這個塊的長度。最後是一個大小爲0的塊,就表示本次迴應的數據發送完了。
-
協議升級(Protocol Switching)
HTTP/1.1 引入了 Upgrade 機制,它使得客戶端和服務端之間可以藉助已有的 HTTP 語法升級到其它協議。
要發起協議升級,客戶端必須在請求首部中指定這兩個字段:
Connection: UpgradeUpgrade: protocol-name[/protocol-version]
如果服務端不同意升級或者不支持 Upgrade 所列出的協議,直接忽略即可(當成 HTTP/1.1 請求,以 HTTP/1.1 響應);如果服務端同意升級,那麼需要這樣響應:
HTTP/1.1 101 Switching ProtocolsConnection: upgradeUpgrade: protocol-name[/protocol-version]
HTTP
Upgrade
響應的狀態碼是 101,並且響應正文可以使用新協議定義的數據格式。 -
Host 首部(Host Header)
使用
HTTP/1.1
發送的請求,必須指明host。因爲在服務器只知道請求的IP,如果兩個域名指向同一個IP,
HTTP/1.0
是無法區分的。但是攜帶host,就能區分了。 -
新增了請求方式PUT、PATCH、OPTIONS、DELETE等。
4. HTTP 2.0
HTTP/2
並沒有改動 HTTP/1
的語義部分,例如請求方法、響應狀態碼、URI 以及首部字段等核心概念依舊存在。HTTP/2
最大的變化是重新定義了格式化和傳輸數據的方式,這是通過在高層 HTTP API 和低層 TCP 連接之間引入二進制分幀層
來實現的。這樣帶來的好處是原來的 WEB 應用完全不用修改,就能享受到協議升級帶來的收益。
HTTP 2.0是下一代HTTP協議,目前應用還非常少。主要特點有:
-
二進制協議(Binary Protocol)
HTTP/1.1 版的頭信息肯定是文本(ASCII編碼),數據體可以是文本,也可以是二進制。HTTP/2 則是一個徹底的二進制協議,頭信息和數據體都是二進制,並且統稱爲"幀"(frame):頭信息幀和數據幀。
二進制協議解析起來更快,更重要的是,相比文本協議,它更少出錯。
-
多路複用(Multiplexed)
HTTP/2 複用TCP連接,在一個連接裏,客戶端和瀏覽器都可以同時發送多個請求或迴應,而且不用按照順序一一對應,這樣就避免了"隊頭堵塞"。
舉例來說,在一個TCP連接裏面,服務器同時收到了A請求和B請求,於是先回應A請求,結果發現處理過程非常耗時,於是就發送A請求已經處理好的部分, 接着迴應B請求,完成後,再發送A請求剩下的部分。
這樣雙向的、實時的通信,就叫做多工(Multiplexing)。
-
擁有優先級(Prioritized)
同時能進行多個請求和響應,所以需要控制順序。
HTTP/2
允許給每個流附上weight
(1~256)和對其他流的依賴,這最終會構建一個優先級樹。 -
服務端推送(Server Push)
允許服務器在給原本請求返回響應的同時,還能主動返回其他資源給客戶端。
在
HTTP/1.X
的時代,有很多連接數優化的網站性能優化方式,比如資源內聯。其實到了新版本,開啓服務端推送,就能幫你解決問題,提升性能。 -
首部壓縮(Header Compression,HPACK)
HTTP 協議不帶有狀態,每次請求都必須附上所有信息。所以,請求的很多字段都是重複的,比如
Cookie
和User Agent
,一模一樣的內容,每次請求都必須附帶,這會浪費很多帶寬,也影響速度。HTTP/2 對這一點做了優化,引入了頭信息壓縮機制(header compression)。一方面,頭信息使用
gzip
或compress
壓縮後再發送;另一方面,客戶端和服務器同時維護一張頭信息表,所有字段都會存入這個表,生成一個索引號,以後就不發送同樣字段了,只發送索引號,這樣就提高速度了。
學習並參考於: