整理了一篇HTTP網(wǎng)絡(luò)知識體系
本文來自@Fishing 讀者投稿,原文鏈接:https://juejin.cn/post/7036608827252277279
一、什么是URI?
URI, 全稱為(Uniform Resource Identifier), 也就是統(tǒng)一資源標(biāo)識符。它并不是我們常說的網(wǎng)址URL, 實(shí)際上URI = URN+URL。
1.URI的結(jié)構(gòu)
它主要由以下幾個(gè)結(jié)構(gòu)組成:

scheme 表示協(xié)議名,比如http,https等
user:passwd@ 表示登錄主機(jī)時(shí)的用戶信息
host 主機(jī)名
port 端口
path 資源路徑
query 表示查詢參數(shù),通常以?開頭多個(gè)值之間以&連接
fragment 頁面資源錨點(diǎn)位置,常見為:https://www.baidu.com/path/index.html#name
2.URI編碼
URI只能使用ASCII, ASCII之外的字符是不支持顯示的。此外,URI引入了編碼機(jī)制,將所有非ASCII碼字符和界定符轉(zhuǎn)為十六進(jìn)制字節(jié)值,然后在前面加個(gè)%,例如:空格被轉(zhuǎn)義成了%20。
二、HTTP狀態(tài)碼你能記住哪些?
HTTP狀態(tài)碼總體分為五類:
| 整體范圍 | 已定義范圍 | 含義 |
|---|---|---|
| 100~199 | 100~101 | 信息提示 |
| 200~299 | 200~206 | 成功 |
| 300~399 | 300~305 | 重定向 |
| 400~499 | 400~415 | 客戶端錯(cuò)誤 |
| 500~599 | 500~505 | 服務(wù)器錯(cuò)誤 |
接下來詳細(xì)看下每個(gè)狀態(tài)碼的含義:
1xx相關(guān)
100
請求中間狀態(tài),客戶端需要繼續(xù)下一步請求。
101
協(xié)議切換。例如當(dāng)HTTP請求升級到websocket服務(wù)的時(shí)候,如果服務(wù)端同意升級,則會返回101狀態(tài)碼。
2xx相關(guān)
200
請求成功。請求中最常見的狀態(tài)碼,也是開發(fā)最喜歡的狀態(tài),表示請求一切正常。
201
成功請求并創(chuàng)建了新的資源。
202
服務(wù)端已接受請求,但未完成處理。
204
沒有內(nèi)容。表示只返回head頭信息,主體內(nèi)容沒返回。
206
表示部分內(nèi)容。常見于大型文件上傳或下載的過程。
3xx相關(guān)
301
永久重定向。將資源永遠(yuǎn)的移到新的域名下。
302
臨時(shí)重定向。將資源臨時(shí)移到新地方,以后還有可能再移回來。
備注:301、302常見于SEO優(yōu)化或http緩存。以http緩存為例:若永久重定向到新資源,則瀏覽器會緩存新資源,并拋棄老域名的緩存。若臨時(shí)重定向則不做緩存優(yōu)化。
304
常見于http緩存。例如 max-age時(shí)間過期,命中協(xié)商緩存的時(shí)候,瀏覽器會攜帶相關(guān)信息到服務(wù)端,服務(wù)器對比信息后發(fā)現(xiàn)文件沒更新可以繼續(xù)使用的情況下就會返回304狀態(tài)碼,意思是告訴客戶端文件可以繼續(xù)使用。
305
使用代理。表示當(dāng)前請求的資源必須通過代理訪問。
307
臨時(shí)重定向,與302類似。
4xx相關(guān)
400
開發(fā)者請求錯(cuò)誤。比較粗糙的提示,具體錯(cuò)誤原因不明。
401
要求請求方,也就是用戶需要進(jìn)行身份認(rèn)證。
403
服務(wù)器拒絕訪問。因法律、敏感詞匯等原因,服務(wù)器拒絕客戶端的請求。
404
資源未找到。這個(gè)很容易理解,也比較常見,服務(wù)端沒有對應(yīng)的資源內(nèi)容的時(shí)候會返回此狀態(tài)碼。
405
請求方法錯(cuò)誤。比較常見于服務(wù)端只支持POST請求,但是開發(fā)者用GET方式請求了接口,就會返回這個(gè)錯(cuò)誤。反之亦然。
406
服務(wù)端資源因某種原因無法滿足客戶端的請求條件。
407
與401類似,要求代理的身份認(rèn)證。
408
客戶端發(fā)送請求時(shí)間超時(shí),服務(wù)器沒有時(shí)間繼續(xù)等待了。
409
服務(wù)器處理內(nèi)容的時(shí)候發(fā)生了沖突。
410
類似404,表示資源以前可能存在,現(xiàn)在被刪除了。
413
客戶端請求體過大,服務(wù)器因無法處理而拒絕。
414
請求的URL地址太長,服務(wù)器無法處理。
5xx相關(guān)
500
服務(wù)器內(nèi)部錯(cuò)誤,具體啥錯(cuò)誤咱也不知道,只知道是出錯(cuò)了。
501
表示服務(wù)器不支持客戶端的請求功能。
502
作為網(wǎng)關(guān)或者代理工作的服務(wù)器嘗試執(zhí)行請求時(shí),從遠(yuǎn)程服務(wù)器接收到了一個(gè)無效的響應(yīng)。
503
服務(wù)器內(nèi)部較忙,暫時(shí)無法相應(yīng)。
504
充當(dāng)網(wǎng)關(guān)或代理的服務(wù)器,未及時(shí)從遠(yuǎn)端服務(wù)器獲取請求。
505
服務(wù)器不支持請求的HTTP協(xié)議的版本,無法完成處理。
三、GET與POST的區(qū)別
-
GET請求會被瀏覽器留下訪問記錄,而POST不會留下記錄; -
GET請求參數(shù)攜帶在URL后面,不太安全,而POST參數(shù)會放到請求體重,適合傳輸敏感數(shù)據(jù); -
GET只能發(fā)送 ASCII 字符,而POST沒限制。 -
發(fā)送數(shù)據(jù)時(shí)機(jī)不同。GET請求會一次性將數(shù)據(jù)發(fā)送出去,而POST發(fā)送分兩部分,先發(fā)送header頭部分,如果服務(wù)端相應(yīng)100狀態(tài)碼(繼續(xù)),然后再發(fā)送body部分。 -
受URL長度限制,GET傳輸數(shù)據(jù)較少,而POST傳輸數(shù)據(jù)量較大,一般默認(rèn)為不受限制。 -
從冪等性的角度來說,GET是冪等的(只要參數(shù)不變,返回的結(jié)果總是相等的),而POST不是。 -
GET在瀏覽器回退時(shí)是無害的,而POST會再次發(fā)起請求。
四、COOKIE相關(guān)
1.什么是cookie
從本質(zhì)上來說,cookie就是存儲在客戶端的一小段文本,以鍵值對的方式存儲在瀏覽器里。通常瀏覽器只會分配4KB的空間給cookie,所以存儲內(nèi)容較少。通常js可以設(shè)置、讀取、刪除cookie,服務(wù)端也可以通過Set-Cookie頭字段對瀏覽器進(jìn)行Cookie寫入。若服務(wù)端設(shè)置屬性為http-only,客戶端js腳本則無法讀取到Cookie值。
以下是百度網(wǎng)站的一段Cookie截圖:
屬性說明:
Name Cookie名稱Value Cookie內(nèi)容
Domain 可以讀取當(dāng)前Cookie的有效域名
Path 可以讀取當(dāng)前Cookie的有效路徑
Expires/Max-Age Cookie有效絕對時(shí)間/過期相對時(shí)間(Session代表當(dāng)前會話期間,網(wǎng)頁關(guān)閉即失效)
Size Cookie大小
HttpOnly 當(dāng)前Cookie是否只能通過http獲取,攜帶到服務(wù)端,js腳本無法獲取
Secure 是否只能通過https傳輸Cookie
SameParty Cookie安全模式,支持三個(gè)值:1、`None`,默認(rèn)模式,http請求默認(rèn)會帶上Cookie值。2、`Lax`模式,只能再GET方法中攜帶Cookie。3、`Strict`,嚴(yán)格模式,只能在當(dāng)前域名下訪問Cookie,其他域名均無法訪問。
Priority 優(yōu)先級,chrome的提案,定義了三種優(yōu)先級,Low/Medium/High,當(dāng)cookie數(shù)量超出時(shí),低優(yōu)先級的cookie會被優(yōu)先清除
2.Cookie的生命周期
我們通常通過Expires和Max-Age這兩個(gè)屬性來設(shè)置Cookie的過期時(shí)間。前者指定過期的具體時(shí)間,后者是過期的相對時(shí)間。若過期,瀏覽器不會主動(dòng)刪除Cookie內(nèi)容,只是無法被讀取到或者無法發(fā)送到服務(wù)端。
3.Cookie的作用域
涉及到兩個(gè)關(guān)鍵詞匯:1、域名(Domain)。2、路徑(Path)。不同域名或路徑下無法相互訪問Cookie內(nèi)容,當(dāng)然頂級域名下的Cookie在子域名之間是共享的,以百度網(wǎng)站為例:.baidu.com下的cookie可以共享給子域名訪問,例如www.baidu.com、tieba.baidu.com等。根路徑(/)下的cookie也可以共享給任何子目錄訪問。
4.安全、性能優(yōu)化相關(guān)
Cookie是以字符串的方式存儲在客戶端,以明文的方式在服務(wù)器與客戶端之間傳輸,容易被攔截修改。不論當(dāng)前請求是否需要Cookie,請求都會攜帶上當(dāng)前域名下的所有Cookie,所以會產(chǎn)生大量不必要的數(shù)據(jù),影響服務(wù)端性能以及帶寬。可以通過設(shè)置Cookie的Domain以及Path適當(dāng)控制攜帶的數(shù)量。
5.其他存儲方式
除了Cookie存儲之外,現(xiàn)代瀏覽器還支持localStorage、sessionStorage存儲,兩者的主要區(qū)別在于前者是永久存儲在瀏覽器,后者的生命周期是會話級別的,網(wǎng)頁關(guān)閉即消失。還有indexDB,感興趣的同學(xué)可參考阮老師的 瀏覽器數(shù)據(jù)庫 IndexedDB 入門教程
五、跨域問題
1.為什么會產(chǎn)生跨域
相信現(xiàn)在絕大多數(shù)公司采用的都是前后端分離的開發(fā)模式,通過Ajax請求響應(yīng)數(shù)據(jù),當(dāng)前訪問網(wǎng)頁的URL與接口地址用的不是一個(gè)域名。這個(gè)時(shí)候?yàn)g覽器就會認(rèn)為是跨域了,存在一定安全隱患。詳細(xì)來說就是請求網(wǎng)頁與接口之間只要滿足以下任一條件,即被認(rèn)為跨域:
-
1、協(xié)議不同 -
2、域名不同 -
3、端口號不同
因?yàn)闉g覽器遵循同源策略,當(dāng)請求與響應(yīng)不同源的時(shí)候,瀏覽器會試圖先發(fā)送一個(gè)OPTIONS預(yù)請求給服務(wù)端,同時(shí)會加上Origin源地址和Host目標(biāo)地址,詢問是否允許跨域,也就是看http返回頭字段Access-Control-Allow-Origin,若是*表示允許任何請求,也可以是指定的請求源地址。若允許則繼續(xù),否則瀏覽器會中斷后續(xù)請求并打印錯(cuò)誤。注意是被瀏覽器攔截了,請求是到達(dá)服務(wù)端了。服務(wù)端發(fā)號施令,控制是否允許跨域,而瀏覽器是實(shí)際執(zhí)行者。
2.常見的跨域解決方案
JSONP
JSONP實(shí)現(xiàn)的原理:雖然XMLHttpRequest對象遵循同源政策,但是script標(biāo)簽不一樣,它可以通過 src 填上目標(biāo)地址從而發(fā)出 GET 請求,實(shí)現(xiàn)跨域請求并拿到響應(yīng)。接下來我們封裝一個(gè)簡單的JSONP:
let myJSONP = (_url,params,callback) => {
let splitUrl = (_url,params) => {
let str = '';
for(let key in params){
str += key+'='+params[key]
}
return _url + '?' + str
}
return new Promise(resolve => {
let _srcipt = document.createElement('script');
_srcipt.src = splitUrl(_url,params);
document.body.appendChild(_srcipt);
window[callback] = res => {
resolve(res)
//渣男,用完即刪除
document.body.removeChild(_srcipt)
}
})
}
Nginx
讓運(yùn)維同學(xué)在Nginx中做反向代理,將所有請求中轉(zhuǎn)一下,讓服務(wù)端識別請求,以為是來自同源的請求,予以通過。
比如說現(xiàn)在客戶端的域名為client.com,服務(wù)器的域名為server.com,客戶端向服務(wù)器發(fā)送 Ajax 請求。Nginx配置方式如下:
server {
listen 443;
server_name client.com;
location /yourApiAddress {
proxy_pass server.com;
}
}
Nginx在其中相當(dāng)于跳板機(jī)的作用。
CORS
開發(fā)同學(xué)代碼中CORS設(shè)置允許任何來源即可。個(gè)人推薦這種配置,基本上一勞永逸,Nginx代理是運(yùn)維同學(xué)設(shè)置的,經(jīng)常遇到服務(wù)器調(diào)整等原因?qū)е驴缬蚍捶磸?fù)復(fù),比較煩人。
其他方式
除此之外就是一些奇淫技巧的跨域解決方案,例如postMessage、iframe等等,現(xiàn)實(shí)中基本上不會用到。就不建議深入了解了,記個(gè)大概即可。
六、HTTP請求方法有哪些
HTTP1.0:GET、POST、HEAD
HTTP1.1:PUT、PATCH、DELETE、OPTIONS、TRACE、CONNECT
| 方法 | 描述 |
|---|---|
| GET | 獲取資源 |
| POST | 資源傳輸,通常會修改服務(wù)器資源 |
| HEAD | 獲得請求頭信息 |
| PUT | 更新資源 |
| DELETE | 刪除資源 |
| PATCH | 對PUT的補(bǔ)充,對已知資源部分更新 |
| OPTIONS | 列出請求資源支持的請求方法,用來跨域請求 |
| TRACE | 追蹤請求/響應(yīng)路徑,用于測試或診斷 |
| CONNECT | 將連接改為管道方式用于代理服務(wù)器 |
七、常見HTTP請求頭有哪些
1.Request Headers
User-Agent 瀏覽器信息,內(nèi)容包含發(fā)出請求的用戶信息。
Cookie 當(dāng)前域名下所有能讀取到的Cookie內(nèi)容,不論服務(wù)器是否需要,都會被攜帶。
Accept 瀏覽器可接受的MIME類型。
Accept-Charset 瀏覽器可接受的字符集。
Accept-Encoding 瀏覽器可接受的壓縮編碼方式,常見的壓縮方式有gzip、br、Servlet
Accept-Language 瀏覽器能接受的語言。
Content-Length 表示請求消息正文的長度。
Authorization 授權(quán)信息,通常出現(xiàn)在對服務(wù)器發(fā)送的WWW-Authenticate頭的應(yīng)答中。
Host 客戶端請求域。
If-Modified-Since 對應(yīng) response返回值 last-Modified 文件最后修改時(shí)間。
If-None-Match 對應(yīng) response返回值 Etag 文件唯一標(biāo)識。
2.Response Headers
Cache-control 詳見下面http緩存一欄,會詳細(xì)講
Content-encoding 壓縮編碼方式,對應(yīng) Accept-Encoding
Content-Length 表示內(nèi)容長度。
Content-Type 表示后面的文檔屬于什么MIME類型
Date 當(dāng)前的GMT時(shí)間。
Expires 告訴客戶端緩存的絕對時(shí)間(目前基本上已不再使用)
Last-Modified 文件最后編輯時(shí)間
Etag 當(dāng)前文件內(nèi)容唯一標(biāo)識,若被重新修改則會有變動(dòng)。
Server 服務(wù)器通過這個(gè)頭告訴瀏覽器服務(wù)器的類型。
八、TCP三次握手
在介紹三次握手之前,先拋出一個(gè)問題:為什么是三次握手,不是兩次或者四次?
首先我們要先理解握手的目的是什么?為了確保雙方的發(fā)送、接收能力正常。就像打電話之前,雙方先“喂喂喂,聽得見嘛”,一個(gè)道理。
最開始客戶端處于CLOSED狀態(tài),服務(wù)器處于LISTEN狀態(tài)(隨時(shí)等待被撩)。
-
第一握手: 客戶端首先發(fā)送一段 SYN報(bào)文,包含生成的序列號,這個(gè)時(shí)候客戶端處于發(fā)送后等待狀態(tài)。 -
第二次握手: 服務(wù)端收到客戶端發(fā)送的 SYN報(bào)文后,將序列號+1后作為ACk應(yīng)答碼返回給客戶端,一并返回的包括服務(wù)端生成的序列號。這個(gè)時(shí)候服務(wù)端就處于半連接狀態(tài),服務(wù)端也能確認(rèn)了客戶端的發(fā)送能力正常,自己的發(fā)送能力、接收能力正常,唯獨(dú)不知道客戶端的接收能力是否正常。所以說二次握手并不能滿足實(shí)際需要。 -
第三次握手: 客戶端接收到服務(wù)端返回的 ACK以及序列號后,將序列號+1作為ACK碼再返回給服務(wù)端。這個(gè)時(shí)候客戶端就能確認(rèn)自己的發(fā)送、接收能力正常,服務(wù)端的發(fā)送、接收能力也正常。服務(wù)端接收到ACK碼之后,將之前的半連接轉(zhuǎn)換成全連接,也就完成了握手連接。
所以,三次握手正好確認(rèn)雙方的發(fā)送、接收能力正常了,再多一次可以嘛?其實(shí)也可以的,只是無用,白白浪費(fèi)了而已,所以三次足以。
備注:三次握手過程中,前兩次不可攜帶數(shù)據(jù),第三次握手可以攜帶數(shù)據(jù)。因?yàn)榍皟纱稳裟軘y帶數(shù)據(jù)的話,攻擊者會利用這個(gè)缺陷發(fā)送大量數(shù)據(jù)給服務(wù)端,而故意忽略第三次,從而導(dǎo)致服務(wù)端產(chǎn)生大量半連接狀態(tài)會話,同時(shí)服務(wù)器要耗費(fèi)更多內(nèi)存去處理數(shù)據(jù),半連接多了,達(dá)到一定數(shù)量后影響正常連接,導(dǎo)致丟包等事件發(fā)生,故而產(chǎn)生SYN攻擊。第三次握手是可以攜帶數(shù)據(jù)的,因?yàn)榈谌挝帐值臅r(shí)候,已經(jīng)建立了正常連接,互相信任了,這個(gè)時(shí)候處理數(shù)據(jù)也無可厚非。
九、TCP四次揮手
有握手的過程,必然就會有分手的過程嘛。四次的過程是這樣的:
-
第一次揮手: 客戶端要斷開連接,向服務(wù)端發(fā)送 FIN報(bào)文,其中會包含客戶端生成的序列號。這個(gè)時(shí)候客戶端處于FIN-WAIT-1狀態(tài),也就是說這個(gè)時(shí)候客戶端處于只能接收、不會再發(fā)送的狀態(tài)。
-
第二次揮手: 服務(wù)端回應(yīng)客戶端狀態(tài)。這個(gè)時(shí)候服務(wù)端也不在接收來自客戶端的數(shù)據(jù),處于 CLOSED-WAIT狀態(tài),但是還有未處理完的數(shù)據(jù)要繼續(xù)處理??蛻舳耸盏椒?wù)端反饋后變成FIN-WAIT2狀態(tài)。
-
第三次揮手: 服務(wù)端處理完最后發(fā)送的數(shù)據(jù)后,再想客戶端發(fā)送 FIN,自己進(jìn)入LAST-ACK狀態(tài)。
-
第四次揮手: 客戶端收到服務(wù)端發(fā)來的 FIN后,自己變成了TIME-WAIT狀態(tài),然后發(fā)送ACK給服務(wù)端。
備注:第三次揮手后,服務(wù)端會間隔一定時(shí)間發(fā)送報(bào)文給客戶端,確??蛻舳耸盏綀?bào)文。只有當(dāng)收到客戶端第四次揮手返回的信息,才不會發(fā)送。所以第四次揮手后,客戶端需要等待足夠長的時(shí)間(2MSL),也就是報(bào)文最大生存時(shí)間,來確保沒有再收到服務(wù)端返回的信息,只要沒收到信息,客戶端就能確保服務(wù)端收到第四次握手信息了,服務(wù)端也確保第三次握手也是成功的了。
十、HTTP緩存
緩存是性能優(yōu)化中非常重要的一環(huán),瀏覽器的緩存機(jī)制對開發(fā)也是非常重要的知識點(diǎn)。接下來以三個(gè)部分來把瀏覽器的緩存機(jī)制說清楚:
-
強(qiáng)緩存 -
協(xié)商緩存 -
緩存位置
1.什么是強(qiáng)緩存、協(xié)商緩存
關(guān)于什么時(shí)候命中強(qiáng)緩存,什么時(shí)候命中協(xié)商緩存,主要依賴于http返回頭信息里的Cache-Control返回字段進(jìn)行控制。
什么情況下命中強(qiáng)緩存?以常見的max-age為例:若max-age=5356800,則意思是說瀏覽器在首次請求這個(gè)文件的時(shí)候,可以在本地磁盤中保存這個(gè)文件5356800秒,從首次加載時(shí)間開始以后的這些時(shí)間內(nèi),若再次請求這個(gè)文件,瀏覽器可以不發(fā)起http請求,而直接使用緩存中的內(nèi)容即可,這樣不僅節(jié)省了服務(wù)器負(fù)擔(dān),也提升網(wǎng)站用戶體驗(yàn)。
什么情況下命中協(xié)商緩存?仍然以常見的max-age為例:若max-age=5356800,距離第一次請求文件已經(jīng)過去了5356800秒,當(dāng)用戶再次需要這個(gè)資源的時(shí)候,瀏覽器就會拿之前這個(gè)文件返回的Etag以及Last-Modified,分別命名為If-None-Match和If-Modified-Since作為請求參數(shù)傳給服務(wù)端,服務(wù)端與現(xiàn)有文件進(jìn)行匹配,若文件已更新,則返回200狀態(tài)碼,同時(shí)返回最新文件給客戶端。若文件未更新,則返回304狀態(tài)碼,告訴客戶端緩存有效,可以繼續(xù)使用。
2.緩存位置
關(guān)于文件緩存位置,可通過Chrome開發(fā)面板中,Network欄目下每個(gè)文件后面有一個(gè)Size屬性查看
-
首次請求,會顯示當(dāng)前文件大小,例如 xxkB。 -
在網(wǎng)頁未關(guān)閉之前,再次請求,會從內(nèi)存中取出文件,顯示 (memory cache)。 -
關(guān)閉網(wǎng)頁再次請求的時(shí)候,若命中強(qiáng)緩存,會從磁盤中取出,顯示 (disk cache)。
3.Cache-Control有哪些字段
public 公共的。表示任何人都可以緩存,包括瀏覽器、代理服務(wù)器等。
private 私有的。表示只允許單個(gè)用戶緩存,不能作為共享緩存。
no-cache 本地可以緩存,但每次都需要與服務(wù)端協(xié)商,即每次都命中協(xié)商緩存。
no-store 不適用任何緩存。
max-age=xxx 設(shè)置緩存最大周期(單位秒),超過這個(gè)相對時(shí)間被認(rèn)為是過期,需要與服務(wù)端協(xié)商是否還可繼續(xù)使用。與Expires不同,因?yàn)樗墙^對時(shí)間,目前基本上已被廢棄,因?yàn)槿舴?wù)器時(shí)間與客戶端時(shí)間相差較大的情況下,會產(chǎn)生一些異常問題。
s-maxage=xxx 設(shè)置代理服務(wù)器緩存文件過期相對時(shí)間,客戶端會忽略它。
must-revalidate 一旦資源過期(比如超過max-age),在成功向原始服務(wù)器驗(yàn)證之前,緩存不能用該資源響應(yīng)后續(xù)請求。
no-transform 不得對資源進(jìn)行轉(zhuǎn)換或轉(zhuǎn)變。
only-if-cached 表明客戶端只接受已緩存的響應(yīng),并且不要向原始服務(wù)器檢查是否有更新的拷貝。
十一、HTTP1.1的缺點(diǎn)
1.無狀態(tài)
其實(shí)這也不能說是缺點(diǎn),這算是它的特點(diǎn)之一,至于是缺點(diǎn)還是優(yōu)點(diǎn),要分場景來看的。那么什么是無狀態(tài)呢?就是指通信過程的上下文信息,每次請求都是獨(dú)立、互相無關(guān)的,且默認(rèn)狀態(tài)不需要保留狀態(tài)信息的。但是在一些場景下,比如前一次請求需要與后一次請求有一定關(guān)聯(lián),這個(gè)時(shí)候無狀態(tài)處理起來就比較麻煩了。
2.臃腫的消息首部
HTTP/1.1 的首部無法壓縮,再加上 cookie 的存在,經(jīng)常會出現(xiàn)首部大小比請求數(shù)據(jù)大小還大的情況。
3.明文傳輸
也就是協(xié)議里的報(bào)文,即傳輸頭信息,不使用二進(jìn)制,而是使用文本的形式傳輸。這就給中間攔截者造成可乘之機(jī),攔截傳輸內(nèi)容,獲取敏感信息。
4.隊(duì)頭阻塞
http傳輸是基于請求-應(yīng)答的模式進(jìn)行的,報(bào)文必須是一發(fā)一收,所有任務(wù)被放到一個(gè)任務(wù)隊(duì)列中串行執(zhí)行。當(dāng)http開啟長連接的時(shí)候,當(dāng)前域名下會共用一個(gè)TCP連接,一旦隊(duì)首因某些原因卡住,后續(xù)只能處于等待狀態(tài),這就是著名的隊(duì)頭阻塞問題。
那么如何解決隊(duì)頭阻塞問題?在不升級到HTTP2.0的前提下,有兩種解決方案:
-
并發(fā)連接。對一個(gè)域名分配多個(gè)長連接,增加多個(gè)任務(wù)隊(duì)列。就像食堂打飯后排隊(duì)付錢,一個(gè)隊(duì)伍排到門口,現(xiàn)在從之前的一個(gè)窗口增加到多個(gè)窗口,同一時(shí)間做付款操作的同學(xué)多了,速度自然也就快起來了。 -
域名分片。上面講到了對一個(gè)域名分配多個(gè)長連接,那么也可以分配多個(gè)域名。例如分配 static1.baidu.com、static2.baidu.com等多個(gè)域名加載網(wǎng)站資源,每個(gè)域名再分配多個(gè)長鏈接,就可以相對解決隊(duì)頭阻塞問題。
注意:域名也不是越多越好,因?yàn)槊慷嘁粋€(gè)域名,都要涉及到DNS查找、TCP三次握手、SSL/TLS握手,且TCP有一個(gè)慢啟動(dòng)特點(diǎn),就是剛開始傳輸慢,慢慢的才會達(dá)到一個(gè)較快的穩(wěn)定速度,如果啟用了一個(gè)單獨(dú)域名,而這個(gè)域名只傳輸了一個(gè)2KB的js文件,實(shí)際文件傳輸時(shí)間遠(yuǎn)遠(yuǎn)小于握手時(shí)間,就得不償失了。具體哪個(gè)地方耗時(shí)可以在Chrome開發(fā)面板下Network中查看具體文件,其中有一個(gè)Waterfall內(nèi)容,截圖示例如下:

名詞解釋
-
Queued at: 從頁面加載到開始請求當(dāng)前文件的等待時(shí)間。 -
Started at: 從第幾秒開始請求當(dāng)前文件。 -
Queueing: 在請求隊(duì)列中的時(shí)間。 -
Stalled: 從TCP 連接建立完成,到真正可以傳輸數(shù)據(jù)之間的時(shí)間差,此時(shí)間包括代理協(xié)商時(shí)間。 -
DNS Lookup: 當(dāng)前域名執(zhí)行DNS查找所花費(fèi)的時(shí)間。 -
Initial Connection: 建立連接所花費(fèi)的時(shí)間,包括TCP握手/重試和協(xié)商SSL。 -
SSL: 完成SSL握手所花費(fèi)的時(shí)間(如果是TLS協(xié)議,此處顯示的就是TLS)。 -
Request sent: 發(fā)出網(wǎng)絡(luò)請求所花費(fèi)的時(shí)間,通常為一毫秒的時(shí)間。 -
Waiting(TFFB): TFFB 是發(fā)出頁面請求到接收到應(yīng)答數(shù)據(jù)第一個(gè)字節(jié)的時(shí)間。 -
Content Download: 接收響應(yīng)數(shù)據(jù)所花費(fèi)的時(shí)間。
十二、HTTP2.0的優(yōu)勢
1.頭部壓縮
HTTP1.1時(shí)代,默認(rèn)情況下前后兩次HTTP請求沒有關(guān)聯(lián),這被稱為無狀態(tài),請求以及響應(yīng)頭信息里有很多字段(本文之前已介紹過),不論是否需要,都會以key:value的形式在網(wǎng)絡(luò)中傳輸,尤其對于GET請求,請求報(bào)文幾乎全是請求頭,這個(gè)時(shí)候就存在非常大的優(yōu)化空間。HTTP2.0就針對這個(gè)問題采用了HPACK壓縮算法對頭部內(nèi)容進(jìn)行壓縮,大大減少了網(wǎng)絡(luò)傳輸。HPACK壓縮算法的特點(diǎn)是啥?在服務(wù)端與客戶端建立一個(gè)哈希表,以索引的形式代替頭信息,雙方傳輸就以索引為準(zhǔn),拿到索引值后到哈希表中尋找對應(yīng)頭內(nèi)容,以此減少網(wǎng)絡(luò)傳輸。
2.多路復(fù)用
上面講到了HTTP1.1隊(duì)頭阻塞的問題,雖然采用了長連接以及多域名分片方法在一定程度上規(guī)避里隊(duì)頭阻塞,但并沒有從根本上解決問題。比如在有限的帶寬情況下,如何完成優(yōu)先級較高的請求,而不是一定要按照排隊(duì)的順序。HTTP2.0是以二進(jìn)制分幀的方式來解決所謂的隊(duì)頭阻塞問題。將原來的Headers、Body的報(bào)文解析成二進(jìn)制的幀數(shù)據(jù),傳輸過程中看到的是10101的格式。這些二進(jìn)制幀不存在先后關(guān)系,因此也就不會排隊(duì)等待,也就沒有了 HTTP 的隊(duì)頭阻塞問題。
注意:所謂的亂序,指的是不同ID的Stream是亂序的,但同一個(gè)Stream ID 的幀一定是按順序傳輸?shù)?。二進(jìn)制幀到達(dá)后對方會將Stream ID相同的二進(jìn)制幀組裝成完整的請求報(bào)文和響應(yīng)報(bào)文。
3.服務(wù)器推送
我們知道在目前的HTTP1.1時(shí)代,服務(wù)器是被動(dòng)的,只有客戶端主動(dòng)發(fā)起請求,服務(wù)端才會響應(yīng)對應(yīng)內(nèi)容,是一問一答的模式。并不會主動(dòng)推送內(nèi)容給客戶端,除非采用websocket。而HTTP2.0就增加了服務(wù)器推送特性,可以對客戶端的一個(gè)請求發(fā)送多個(gè)響應(yīng)。比如客戶端請求html頁面的時(shí)候,服務(wù)器可以將當(dāng)前頁面用到的js以及css等資源一并返回給客戶端,減少后續(xù)交互。
當(dāng)然,客戶端也可以拒絕服務(wù)器的推送。
4.解析速度快
服務(wù)器解析 HTTP1.1 的請求時(shí),必須不斷地讀入字節(jié),直到遇到分隔符 CRLF 為止。而解析 HTTP2 的請求就不用這么麻煩,因?yàn)?HTTP2.0是基于幀的協(xié)議,每個(gè)幀都有表示幀長度的字段。
5.優(yōu)先級
HTTP2.0可以對比較緊急的請求設(shè)置一個(gè)較高的優(yōu)先級,服務(wù)器在收到這樣的請求后,可以優(yōu)先處理。
十三、HTTPS知識點(diǎn)
HTTPS是超文本傳輸安全協(xié)議,加強(qiáng)版的HTTP,在HTTP的基礎(chǔ)上對headers、body進(jìn)行加密后再傳輸,大大增加了安全性。簡單的講,HTTPS = HTTP + SSL/TLS。
至于為何安全,簡要的說就是在之前HTTP明文傳輸?shù)幕A(chǔ)上增加了對稱加密、不對稱加密算法。至于加密的原理及過程,需要額外一篇文章來詳細(xì)講解,感興趣的同學(xué)可查閱相關(guān)資料,這里不再贅述。
與前端相關(guān)的另外一個(gè)HTTPS知識點(diǎn)就是:HTTPS在HTTP握手的基礎(chǔ)上又增加了一層SSL/TLS握手。所以安全是要有一定代價(jià)的,代價(jià)就是在真正連接前又多了個(gè)握手的過程。握手的過程這里不再贅述,感興趣的同學(xué)可查閱相關(guān)資料。主要分以下三類:
-
RSA 握手 -
TLS1.2 握手 -
TLS1.3 握手
十四、HTTP和HTTPS的區(qū)別
-
HTTP是明文傳輸,不安全的,HTTPS是加密傳輸,安全的多。 -
HTTP標(biāo)準(zhǔn)端口是80,HTTPS標(biāo)準(zhǔn)端口是443。 -
HTTP不用認(rèn)證證書免費(fèi),HTTPS需要認(rèn)證證書要錢。 -
連接方式不同, HTTP三次握手,HTTPS中TLS1.2版本7次,TLS1.3版本6次。 -
HTTP在OSI網(wǎng)絡(luò)模型中是在應(yīng)用層,而HTTPS的TLS是在傳輸層。 -
HTTP是無狀態(tài)的,HTTPS是有狀態(tài)的。
十五、HTTP代理
目前通常意義上的代理,一般認(rèn)為是CDN節(jié)點(diǎn),就是架設(shè)在客戶端與原服務(wù)器之間的服務(wù)器,對客戶端來說它就是服務(wù)器,對服務(wù)器來說它就是客戶端。主要起到負(fù)載均衡的作用,減少原服務(wù)器的壓力,分擔(dān)原服務(wù)器帶寬,提高用戶訪問資源速度,提高用戶體驗(yàn)。
什么是CDN
默認(rèn)情況下,所有資源都會向原服務(wù)器請求。這不僅會給原服務(wù)器造成較大壓力,還會因距離問題讓客戶端等待較長時(shí)間,例如服務(wù)器在美國,中國用戶首次請求要跨越大半個(gè)地球,顯然比從上海服務(wù)器請求更慢。這個(gè)時(shí)候?qū)τ谠?wù)器來說,就需要個(gè)代理,這個(gè)代理服務(wù)器就被稱為CDN節(jié)點(diǎn),節(jié)點(diǎn)按照一定規(guī)則定期向原服務(wù)器更新文件即可,附近的用戶就近訪問當(dāng)前節(jié)點(diǎn)即可,既減輕了原服務(wù)器壓力,也減少了請求時(shí)間,提高用戶體驗(yàn)。
代理常見頭部字段
Via
是一個(gè)能用首部,由代理服務(wù)器添加,適用于正向和反向代理,在請求和響應(yīng)首部均可出現(xiàn),這個(gè)消息首部可以用來追蹤消息轉(zhuǎn)發(fā)情況,防止循環(huán)請求,還可以識別在請求或響應(yīng)傳遞鏈中消息發(fā)送者對于協(xié)議的支持能力。
Via: 1.1 vegur
Via: HTTP/1.1 GWA
Via: 1.0 fred, 1.1 p.yourAddress.net
X-Forwarded-For
是一種獲取用戶真實(shí)IP的字段,不管中間經(jīng)過多少代理,這個(gè)字段始終記錄最初的客戶端的IP。
相應(yīng)的,還有X-Forwarded-Host和X-Forwarded-Proto,分別記錄客戶端(注意:不包括代理)的域名和協(xié)議名。
X-Real-IP
一般記錄真實(shí)發(fā)出請求的客戶端的IP,還有X-Forwarded-Host和X-Forwarded-Proto分別記錄真實(shí)發(fā)出請求的客戶端的域名和協(xié)議名。
十六、http性能優(yōu)化相關(guān)
其實(shí)能看到這里,相信你的心里已經(jīng)對網(wǎng)絡(luò)性能優(yōu)化有一定的想法了,這里也就做一些簡單的知識點(diǎn)羅列。
-
DNS預(yù)解析 -
合理控制域名數(shù)量 -
使用HTTP2.0 -
采用服務(wù)端渲染+客戶端渲染的方式 -
公共類庫存放到CDN上 -
http返回值 Cache-Control的max-age設(shè)置較大值,例如6個(gè)月,盡可能保持一直緩存,文件更改的時(shí)候還一個(gè)hash文件名即可。 -
將CSS放在文件頭部,JavaScript文件放在底部 -
使用字體圖標(biāo)iconfont代替圖片圖標(biāo) -
小圖片采用base64壓縮,減少網(wǎng)絡(luò)請求 -
js、css文件壓縮,服務(wù)端采用gzip、br等壓縮算法 -
圖片懶加載。這對于首屏優(yōu)化非常有用,非首屏需要的圖片在網(wǎng)絡(luò)空閑的時(shí)候異步加載即可 -
關(guān)于圖片,也可以適當(dāng)降低圖片質(zhì)量,或者先加載一個(gè)質(zhì)量較低的圖片顯示給用戶看,之后再加載清晰的圖片展示給用戶。 -
使用css3代理部分圖標(biāo) -
webpack配置按需加載 -
減少重繪重排 -
使用requestAnimationFrame來實(shí)現(xiàn)視覺變化 -
使用Web Workers -
降低CSS選擇器的復(fù)雜性 -
使用flexbox布局 -
使用transform和opacity屬性更改來實(shí)現(xiàn)動(dòng)畫 -
最后一條建議:避免過度優(yōu)化
