異步請(qǐng)求為什么會(huì)導(dǎo)致tcp的對(duì)頭阻塞

這個(gè)異步指的是網(wǎng)絡(luò)請(qǐng)求不會(huì)阻塞其后 js 代碼繼續(xù)執(zhí)行和瀏覽器渲染頁(yè)面其他的部分。

同步和異步

同步和異步關(guān)注的是消息通信機(jī)制

同步就是在發(fā)出一個(gè)調(diào)用后,在沒(méi)有得到結(jié)果之前,該調(diào)用就不返回。但是一旦調(diào)用返回,就得到返回值了。換句話說(shuō),就是由調(diào)用者主動(dòng)等待這個(gè)調(diào)用的結(jié)果。

異步就是調(diào)用發(fā)出后,這個(gè)調(diào)用就直接返回了,所以沒(méi)有返回結(jié)果。換句話說(shuō)調(diào)用者不會(huì)立刻得到結(jié)果而是在調(diào)用返回的時(shí)候被調(diào)用者通過(guò)狀態(tài)、通知來(lái)通知調(diào)用者,或通過(guò)回調(diào)函數(shù)處理這個(gè)調(diào)用。

舉個(gè)通俗的例子:

你打電話問(wèn)書店老板有沒(méi)有《分布式系統(tǒng)》這本書,如果是同步通信機(jī)制,書店老板會(huì)說(shuō),你稍等,”我查一下",然后開始查啊查,等查好了(可能是 5 秒,也可能是一天)告訴你結(jié)果(返回結(jié)果)。
而異步通信機(jī)制,書店老板直接告訴你我查一下啊,查好了打電話給你,然后直接掛電話了(不返回結(jié)果)。然后查好了,他會(huì)主動(dòng)打電話給你。在這里老板通過(guò)“回電”這種方式來(lái)回調(diào)。

阻塞和非阻塞

阻塞和非阻塞關(guān)注的是程序在等待調(diào)用結(jié)果時(shí)的狀態(tài).

阻塞調(diào)用是指調(diào)用結(jié)果返回之前,當(dāng)前線程會(huì)被掛起。調(diào)用線程只有在得到結(jié)果之后才會(huì)返回。非阻塞調(diào)用指在不能立刻得到結(jié)果之前,該調(diào)用不會(huì)阻塞當(dāng)前線程。

你打電話問(wèn)書店老板有沒(méi)有《分布式系統(tǒng)》這本書,你如果是阻塞式調(diào)用,你會(huì)一直把自己“掛起”,直到得到這本書有沒(méi)有的結(jié)果,如果是非阻塞式調(diào)用,你不管老板有沒(méi)有告訴你,你自己先一邊去玩了, 當(dāng)然你也要偶爾過(guò)幾分鐘 check 一下老板有沒(méi)有返回結(jié)果。

在這里阻塞與非阻塞與是否同步異步無(wú)關(guān)。跟老板通過(guò)什么方式回答你結(jié)果無(wú)關(guān)。

對(duì)頭阻塞

http 的對(duì)頭阻塞

對(duì)于長(zhǎng)鏈接來(lái)說(shuō):同一個(gè) tcp 連接上下一個(gè)請(qǐng)求發(fā)出之前需要等到上一個(gè)請(qǐng)求的結(jié)果返回,所以如果前一個(gè)請(qǐng)求的處理時(shí)間較長(zhǎng)或者是被掛起,那么后面的請(qǐng)求就會(huì)一直排隊(duì)等待。(所以 http 長(zhǎng)鏈接的對(duì)頭阻塞發(fā)生在客戶端)

對(duì)于 http1.1 的管道化來(lái)說(shuō):同一個(gè) tcp 連接上可以同時(shí)發(fā)送多個(gè)請(qǐng)求,服務(wù)器也可以同時(shí)處理這些請(qǐng)求,但是響應(yīng)必須要按照順序返回。如果最先收到的請(qǐng)求的處理時(shí)間長(zhǎng)的話,響應(yīng)生成也慢,就會(huì)阻塞已經(jīng)生成了的響應(yīng)的發(fā)送。也會(huì)造成隊(duì)首阻塞。 http1.1 管道化的對(duì)頭阻塞發(fā)生在服務(wù)器端(瀏覽器默認(rèn)是禁止使用管道化的,所以并發(fā)請(qǐng)求的處理方式只能是同時(shí)建立多個(gè) tcp 連接,但是這就會(huì)收到瀏覽器對(duì)同一域名下并發(fā)連接數(shù)的限制。現(xiàn)代瀏覽器默認(rèn)是不開啟 HTTP Pipelining 的

管道化的定義:一個(gè)支持持久連接的客戶端可以在一個(gè)連接中發(fā)送多個(gè)請(qǐng)求(不需要等待任意請(qǐng)求的響應(yīng))。收到請(qǐng)求的服務(wù)器必須按照請(qǐng)求收到的順序發(fā)送響應(yīng)。
至于標(biāo)準(zhǔn)為什么這么設(shè)定,我們可以大概推測(cè)一個(gè)原因:由于 HTTP/1.1 是個(gè)文本協(xié)議,同時(shí)返回的內(nèi)容也并不能區(qū)分對(duì)應(yīng)于哪個(gè)發(fā)送的請(qǐng)求,所以順序必須維持一致。比如你向服務(wù)器發(fā)送了兩個(gè)請(qǐng)求 GET /query?q=A 和 GET /query?q=B,服務(wù)器返回了兩個(gè)結(jié)果,瀏覽器是沒(méi)有辦法根據(jù)響應(yīng)結(jié)果來(lái)判斷響應(yīng)對(duì)應(yīng)于哪一個(gè)請(qǐng)求的。

http2 的多路復(fù)用解決了 http 層面的對(duì)頭阻塞。HTTP2 不使用管道化的方式,而是引入了幀、消息和數(shù)據(jù)流等概念,每個(gè)請(qǐng)求/響應(yīng)被稱為消息,一個(gè)流代表一個(gè)完整的請(qǐng)求或者響應(yīng)。每個(gè)消息都被拆分成若干個(gè)幀進(jìn)行傳輸,每個(gè)幀都分配一個(gè)序號(hào)。不同流的幀可以亂序發(fā)送,同一個(gè)流的幀需要順序發(fā)送。每個(gè)幀在傳輸是屬于一個(gè)數(shù)據(jù)流,而一個(gè)連接上可以存在多個(gè)流,每個(gè)流都可以承載雙向的消息。各個(gè)幀在流和連接上獨(dú)立傳輸,到達(dá)之后在組裝成消息,這樣就避免了請(qǐng)求/響應(yīng)阻塞。

但是即使是使用 http2,它底層也是使用 tcp,所以它依然存在 tcp 層面的對(duì)頭阻塞

tcp 的對(duì)頭阻塞

TCP 的阻塞問(wèn)題是因?yàn)閭鬏旊A段可能會(huì)丟包,一旦丟包就會(huì)等待重新發(fā)包,其后面的數(shù)據(jù)包即使到達(dá)接收端,也不會(huì)被處理而是存放在緩沖區(qū),等待這個(gè)丟失的包被發(fā)送端重新傳到接收端,然后再將收到的數(shù)據(jù)包按順序進(jìn)行組裝處理。

如何解決 tcp 的對(duì)頭阻塞

TCP 中的隊(duì)頭阻塞的產(chǎn)生是由 TCP 自身的實(shí)現(xiàn)機(jī)制決定的,無(wú)法避免。想要在應(yīng)用程序當(dāng)中避免 TCP 隊(duì)頭阻塞帶來(lái)的影響,只有舍棄 TCP 協(xié)議。

比如 google 推出的 quic 協(xié)議,在某種程度上可以說(shuō)避免了 TCP 中的隊(duì)頭阻塞,因?yàn)樗静皇褂?TCP 協(xié)議,而是在 UDP 協(xié)議的基礎(chǔ)上實(shí)現(xiàn)了可靠傳輸。而 UDP 是面向數(shù)據(jù)報(bào)的協(xié)議,數(shù)據(jù)報(bào)之間不會(huì)有阻塞約束。

此外還有一個(gè) SCTP(流控制傳輸協(xié)議),它是和 TCP、UDP 在同一層次的傳輸協(xié)議。SCTP 的多流特性也可以盡可能的避免隊(duì)頭阻塞的情況。

總結(jié)

從 TCP 隊(duì)頭阻塞和 HTTP 隊(duì)頭阻塞的原因我們可以看到,出現(xiàn)隊(duì)頭阻塞的原因有兩個(gè):

  • 獨(dú)立的消息數(shù)據(jù)都在一個(gè)鏈路上傳輸,也就是有一個(gè)“隊(duì)列”。比如 TCP 只有一個(gè)流,多個(gè) HTTP 請(qǐng)求共用一個(gè) TCP 連接

  • 隊(duì)列上傳輸?shù)臄?shù)據(jù)有嚴(yán)格的順序約束。比如 TCP 要求數(shù)據(jù)嚴(yán)格按照序號(hào)順序,HTTP 管道化要求響應(yīng)嚴(yán)格按照請(qǐng)求順序返回

所以要避免隊(duì)頭阻塞,就需要從以上兩個(gè)方面出發(fā),比如 quic 協(xié)議不使用 TCP 協(xié)議而是使用 UDP 協(xié)議,SCTP 協(xié)議支持一個(gè)連接上存在多個(gè)數(shù)據(jù)流等等。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容