-
起因
我們都知道http請(qǐng)求基于tcp協(xié)議,那么瀏覽器處理頁(yè)面上的 圖片,ajax請(qǐng)求時(shí),是同時(shí)建立多個(gè)tcp協(xié)議還是一個(gè)tcp協(xié)議重復(fù)使用
-
問題
問題1 :
瀏覽器是否有線程池的概念,維護(hù)針對(duì)一個(gè)服務(wù)器的tcp協(xié)議線程池,當(dāng)頁(yè)面請(qǐng)求多的時(shí)候并發(fā)調(diào)用。維護(hù)tcp線程池是雙向的服務(wù)器同樣也需要維護(hù),那服務(wù)器不同意怎么辦?
- 問題2 :
一個(gè)tcp鏈接處理http請(qǐng)求時(shí),可以并發(fā)處理么,比如同時(shí)傳5個(gè)請(qǐng)求,等待五個(gè)請(qǐng)求返回 。
-
說說結(jié)論
問題1 :
- 常用瀏覽器都有tcp協(xié)議線程池的概念,他們不會(huì)無限制增加tcp線程池,不同瀏覽器設(shè)置了不同的上限,針對(duì)一個(gè)服務(wù)器建立的tcp鏈接的數(shù)量。
- http/1.0 協(xié)議中沒有對(duì) 建立連接tcp保持連接進(jìn)行設(shè)定,所以每次發(fā)完http請(qǐng)求后斷開鏈接,下一個(gè)請(qǐng)求重新建立,中間開銷極大。 所以http/1.1 協(xié)議header中支持Connection ,默認(rèn)支持將tcp協(xié)議維護(hù)一段時(shí)間,除非有請(qǐng)求頭中寫明 Connection: close
證明:
這是通過chrome兩次 打開 (https://www.baidu.com/) 百度所使用的時(shí)間??梢钥吹降谝淮未蜷_時(shí),進(jìn)行了dns解析,ssl 協(xié)議驗(yàn)證,以及有一個(gè)初始鏈接的情況,但是第二次沒有,也就是說第二次訪問的時(shí)候使用了建立好的tcp鏈接。
服務(wù)器如果不支持是什么樣子的呢:
懶得實(shí)驗(yàn)了,有空再說
nginx不像apache,直接有指令keep-alive off/on;它使用的是keepalive_timeout [time],默認(rèn)的時(shí)長(zhǎng)為75,可以在http、server、location使用此指令。
問題2 :
瀏覽器一般是不支持請(qǐng)求周期重疊的,一個(gè)tcp鏈接只能處理一個(gè)請(qǐng)求,只能一個(gè)發(fā)送成功返回之后在發(fā)送另外一個(gè)。
但是1.1協(xié)議中也做了相應(yīng)的努力 通過規(guī)定 Pipelining 來解決問題,簡(jiǎn)單來說協(xié)議內(nèi)容就是 客戶端按照順序?qū)懭胝?qǐng)求,服務(wù)器按照順序返回
那瀏覽器一般不支持的原因是什么呢:
并不是所有的請(qǐng)求都是通過瀏覽器直達(dá)服務(wù)器,一部分代理服務(wù)器對(duì)Pipelining支持不友好
你同一個(gè)tcp 并發(fā) 多個(gè)請(qǐng)求,在服務(wù)端也會(huì)挨個(gè)處理,假設(shè)一個(gè)請(qǐng)求被阻塞時(shí),同期發(fā)送的tcp請(qǐng)求就會(huì)被阻塞。
那就沒辦法了?
其實(shí) 使用http/1.1 協(xié)議不行的話,我們可以使用http2 協(xié)議
當(dāng)然http2 協(xié)議是建立在https 協(xié)議的基礎(chǔ)上,如果你的http協(xié)議訪問,就沒辦法了。
相對(duì)于http/1.1協(xié)議 使用文本格式, http2 協(xié)議引入了數(shù)據(jù)流和幀的概念, 簡(jiǎn)單來說就是壓縮了請(qǐng)求體,對(duì)每個(gè)請(qǐng)求體進(jìn)行了編號(hào)也就是(幀) ,返回的數(shù)據(jù)可以根據(jù)(幀)來判斷是哪個(gè)請(qǐng)求 (Multiplexing 多路傳輸特性)
可以想象 并發(fā)對(duì)頁(yè)面加載速度的提升是很顯著的:
做個(gè)簡(jiǎn)單的計(jì)算,
....算了不計(jì)算了 大體就是并發(fā)效率高
瀏覽器發(fā)現(xiàn)有大量的https的圖片請(qǐng)求時(shí),發(fā)起tcp鏈接前會(huì)先詢問一下是否支持http2,如果不支持,就走h(yuǎn)ttp/1.1協(xié)議。