HTTP 發(fā)展史
http1.0中飞袋,每請求一個http請求都需要建立一次tcp連接怯疤,而tcp的三次握手
和四次揮手
相對比較耗時讹语,且會帶來1.5+2=3.5個RTT
因此在http1.1中售担,引入了長鏈接
的概念,當(dāng)在請求頭部設(shè)置了Connection:keep-alive
時辫愉,表示一個http請求完成不會斷開連接栅受,而是接著發(fā)送下一下http連接,然而http請求是按照順序請求的,如果一個http延遲了屏镊,隊列后面的所有請求都會延遲依疼,這就是隊頭阻塞
問題斩披。http1.1同時規(guī)定一個域名同時可以有6個tcp連接崇棠,這6個tcp連接中的http請求是可以并行的,但是每個tcp是一個慢啟動
的過程,tcp發(fā)送數(shù)據(jù)的過程類似于地鐵啟動,比較耗時(慢啟動
是tcp為了減少網(wǎng)絡(luò)擁塞的一種策略)蔚出,并且6個tcp連接直接會對帶寬進(jìn)行競爭,導(dǎo)致tcp會動態(tài)的減慢接收數(shù)據(jù)的速度虫腋,而不會管資源是否是關(guān)鍵資源
骄酗。并且http1.1還支持了虛擬主機(jī)
(Host字段)和客戶端Cookie
,虛擬主機(jī)有不同的域名悦冀,但只想同一個Ip地址趋翻,這樣瀏覽器和同一個服務(wù)器就不止可以有6個tcp連接了。
因此在http2.0中盒蟆,引入了多路復(fù)用
踏烙,只需要一個tcp連接,多路復(fù)用
解決了隊頭阻塞
和多個tcp的慢啟動以及競爭問題历等。多路復(fù)用的實現(xiàn)是:在網(wǎng)絡(luò)層級中增加了二進(jìn)制分幀層
讨惩,不同的請求包會被加上編號,同時可以發(fā)送不同請求的包寒屯,客戶端和服務(wù)端會根據(jù)編號來拼湊出一個完整的包荐捻。并且http2.0中支持給請求設(shè)置優(yōu)先級
(這樣服務(wù)器就會優(yōu)先處理這些請求并返回)、服務(wù)器推送
(服務(wù)器在接收到html請求后寡夹,會附帶將html中引用的js燈發(fā)送給瀏覽器)和頭部壓縮
功能处面。但是http2.0依然是基于tcp協(xié)議的,tcp依然存在數(shù)據(jù)包級別的隊頭阻塞問題菩掏,即在數(shù)據(jù)傳輸?shù)倪^程中如果丟包了魂角,那么整個tcp連接會處于一個暫停狀態(tài),等待數(shù)據(jù)包的重傳智绸,這是tcp只所以是可靠協(xié)議
的原因野揪。
HTTP 方法
- head:請求資源的頭部信息,可以在下載一個大文件前先獲取其大小在決定是否要下載以節(jié)約帶寬传于。
- patch:用于對資源進(jìn)行部分修改囱挑。
- get
- post
- put
- delete
如何保證頁面文件能被完整地送達(dá)瀏覽器呢?
- 互聯(lián)網(wǎng)中的數(shù)據(jù)是通過數(shù)據(jù)包來傳輸?shù)恼恿铮瑪?shù)據(jù)包在傳輸過程中容易丟失或出錯平挑。
- IP 負(fù)責(zé)把數(shù)據(jù)包送達(dá)目的主機(jī)。
- UDP 負(fù)責(zé)把數(shù)據(jù)包送達(dá)具體應(yīng)用。
- TCP 保證了數(shù)據(jù)完整地傳輸通熄,它的連接可分為三個階段:建立連接唆涝、傳輸數(shù)據(jù)和斷開連接。
HTTP是基于TCP的協(xié)議唇辨,因此建立HTTP連接的第一步是建立TCP連接廊酣,而建立TCP連接的第一步是獲取ip和port,所以第一步就是dns解析赏枚,根據(jù)域名拿到ip和port亡驰。然而,同一個域名下饿幅,最多只可以建立6個TCP連接(HTTP1.1凡辱,而http2同個域名只能維持一個長連接。)栗恩。所以拿到ip和Port后并不是直接連接連接透乾。域名也會有重定向的問題,如果瀏覽器返回相應(yīng)報文中磕秤,狀態(tài)碼是301或302乳乌,并有一個Location字段,表示該域名需要重定向到另一個地址市咆,該操作是服務(wù)器設(shè)置的汉操。
Content-Type 是 HTTP 頭中一個非常重要的字段, 它告訴瀏覽器服務(wù)器返回的響應(yīng)體數(shù)據(jù)是什么類型
HTTP是一個無狀態(tài)協(xié)議床绪,那么登錄狀態(tài)是如何保持的客情?
cookie方式
- 瀏覽器發(fā)送用戶信息到服務(wù)器
- 服務(wù)器校驗用戶合法后,生成一段表示用戶的字符串癞己,并寫入到響應(yīng)頭的Set-Cookie字段中
- 瀏覽器解析響應(yīng)頭膀斋,將cookie信息保存到本地
- 當(dāng)瀏覽器再次發(fā)送請求時,會讀取本地存儲的cookie中痹雅,并將其寫入請求頭的Cookie字段中
- 服務(wù)器收到請求后仰担,解析請求頭,獲取Cookie字段中的信息绩社,然后查詢后臺摔蓝,判斷該用戶為已登錄狀態(tài),然后返回對應(yīng)數(shù)據(jù)
token方式 - 前端發(fā)送用戶信息到服務(wù)器
- 服務(wù)器校驗用戶合法后愉耙,會根據(jù)密鑰贮尉、過期時間和一些加密算法生成token
- 前端將token保存下來
- 當(dāng)前端再次發(fā)送請求時,會攜帶上token值
- 服務(wù)器收到請求后朴沿,若還有有效期則返回數(shù)據(jù)猜谚,若過期會返回響應(yīng)狀態(tài)碼败砂,前端根據(jù)狀態(tài)碼做一些處理,如跳轉(zhuǎn)到登錄頁魏铅,要求用戶重新登錄
瀏覽器的URL導(dǎo)航流程昌犹?
渲染流程?
JavaScript -> Style -> Layout(布局览芳,回流) -> Paint(繪制) -> Composite(合成)
當(dāng)從服務(wù)器接收HTML頁面的第一批數(shù)據(jù)時斜姥,DOM解析器就開始工作了,在解析過程中沧竟,如果遇到了JS腳本铸敏,如下所示:
<html>
<body>
極客時間
<script>
document.write("--foo")
</script>
</body>
</html>
那么DOM解析器會先執(zhí)行JavaScript腳本,執(zhí)行完成之后屯仗,再繼續(xù)往下解析搞坝。
那么第二種情況復(fù)雜點(diǎn)了,我們內(nèi)聯(lián)的腳本替換成js外部文件魁袜,如下所示:
<html>
<body>
極客時間
<script type="text/javascript" src="foo.js"></script>
</body>
</html>
這種情況下,當(dāng)解析到JavaScript的時候敦第,會先暫停DOM解析峰弹,并下載foo.js文件,下載完成之后執(zhí)行該段JS文件芜果,然后再繼續(xù)往下解析DOM鞠呈。這就是JavaScript文件為什么會阻塞DOM渲染。
我們再看第三種情況右钾,還是看下面代碼:
<html>
<head>
<style type="text/css" src = "theme.css" />
</head>
<body>
<p>極客時間</p>
<script>
let e = document.getElementsByTagName('p')[0]
e.style.color = 'blue'
</script>
</body>
</html>
當(dāng)我在JavaScript中訪問了某個元素的樣式蚁吝,那么這時候就需要等待這個樣式被下載完成才能繼續(xù)往下執(zhí)行,所以在這種情況下舀射,CSS也會阻塞DOM的解析窘茁。