持久連接

什么是持久連接?在事務(wù)處理結(jié)束之后仍然保持在打開狀態(tài)的TCP連接被成為持久連接。非持久連接會(huì)在每個(gè)事務(wù)結(jié)束之后關(guān)閉,持久連接會(huì)在不同事務(wù)之間保持打開狀態(tài),直到客戶端或服務(wù)器決定將其關(guān)閉為止。重用持久連接,就可以避開緩慢的連接建立階段。而且已經(jīng)打開的連接還可以避免慢啟動(dòng)的擁擠適應(yīng)階段,以便更快地進(jìn)行數(shù)據(jù)的傳輸。

可是這樣會(huì)造成網(wǎng)絡(luò)使用效率的降低,為什么呢?有這么幾點(diǎn)原因

    1. 每次建立連接的時(shí)候都要經(jīng)過(guò)三次握手等必須的程序,如果我們擁有一條可以一直使用的連接的話,也就意味著我們只需要進(jìn)行一次連接的建立,這就省去了每次建立連接的時(shí)間。
    1. 使用過(guò)的連接會(huì)比新建立的連接速度會(huì)快一些,這是由于TCP連接慢啟動(dòng)的特性,每次建立新的連接,當(dāng)然不如已經(jīng)被調(diào)教的很好的連接速度快咯。
    1. 每個(gè)連接對(duì)于服務(wù)器和客戶端來(lái)說(shuō)都是負(fù)擔(dān),能少開盡量少開,當(dāng)然是在不影響功能和體驗(yàn)的前提下。

現(xiàn)在很多方案都會(huì)采用持久連接+新連接結(jié)合的方式,這種方式盡可能的減少了新建連接的浪費(fèi),同時(shí)當(dāng)現(xiàn)有連接沒(méi)有辦法滿足需求的時(shí)候,可以建立新連接滿足需求,比較靈活?,F(xiàn)有的持久連接類型有兩種:
HTTP/1.0+的keep-alive和HTTP/1.1的persistent
keep-alive

keep-alive:
image.png

這個(gè)是百度首頁(yè)的一個(gè)HTTP事務(wù),可以看到有個(gè)首部connection:keep-alive,這個(gè)就是第一種持久連接了。下面來(lái)看下這個(gè)持久連接是怎么建立的:

image.png

這個(gè)就是請(qǐng)求的過(guò)程了:

客戶端先發(fā)出請(qǐng)求,以connection:keep-alive的形式傳向服務(wù)器,
如果服務(wù)器接受的請(qǐng)求的話響應(yīng)中就會(huì)帶有connection:keep- alive

當(dāng)使用了connection:keep-alive時(shí),可以使用keep-alive首部傳遞一些關(guān)于持久連接的參數(shù):
timeout:表示持續(xù)時(shí)間,
max:表示希望還在這條持久連接上傳輸多少個(gè)HTTP服務(wù)
但是這些都不是承諾值,也就是說(shuō)隨時(shí)都可以反悔。

keep-alive持久連接需要注意的一些地方:
    1. 如果要是用持久連接,那么就一定要有正確的content-length這個(gè)描述主體長(zhǎng)度的首部,因?yàn)槌志眠B接會(huì)連續(xù)的傳輸HTTP事務(wù),而判斷連續(xù)的HTTP事 務(wù)之間的分界點(diǎn)就是靠content-length告訴的主體的長(zhǎng)度了,如果錯(cuò)誤或沒(méi)有告訴主體的長(zhǎng)度的話,那么就沒(méi)辦法知道這個(gè)事務(wù)在哪里結(jié)束了。
    1. 代理和網(wǎng)管必須再轉(zhuǎn)發(fā)之前刪除connection:keep-alive這個(gè)首部,這個(gè)涉及到啞代理問(wèn)題,后面會(huì)說(shuō)到。
    1. 因?yàn)槌志眠B接可以隨時(shí)關(guān)閉,所以一定要做好遇到當(dāng)請(qǐng)求發(fā)出去響應(yīng)還沒(méi)回送回來(lái)的時(shí)候持久連接就斷開的情況的準(zhǔn)備,也就是有些時(shí)候可能要從新發(fā)送請(qǐng)求。
啞代理和聰明的代理
啞代理只是單純的轉(zhuǎn)發(fā)請(qǐng)求,并不能進(jìn)行解析處理、維持持久連接等其他工作,而聰明的代理可以解析接收到的報(bào)文同時(shí)可以維持持久連接。
image.png

如上圖,當(dāng)客戶端與服務(wù)器之間存在不解析直接轉(zhuǎn)發(fā)的代理時(shí),connection:keep-alive這個(gè)首部是直接轉(zhuǎn)發(fā)給服務(wù)器的,服務(wù)器接收了這個(gè)請(qǐng)求之后,就會(huì)向客戶端發(fā)送帶有connection:keep-alive的響應(yīng),同樣盲代理不會(huì)解析響應(yīng),直接將全部響應(yīng)轉(zhuǎn)發(fā)回客戶端。因?yàn)榭蛻舳耸盏搅诉@個(gè)首部,就認(rèn)為建立持久連接已經(jīng)成功了,但是中間的”笨代理“,并不知道這些事情,笨代理只有一種行為模式:在轉(zhuǎn)發(fā)請(qǐng)求和回送服務(wù)器響應(yīng)請(qǐng)求之后就認(rèn)為這次事務(wù)結(jié)束了,等待連接斷開,而這時(shí)由于connection:keep-alive首部已經(jīng)發(fā)送到服務(wù)器和客戶端,雙方都認(rèn)為持久連接已經(jīng)建立完成,這樣就變成了兩邊認(rèn)為持久連接OK而中間的啞代理等待連接斷開的情況,這種情況下如果客戶端再一次在這條連接上發(fā)送請(qǐng)求,請(qǐng)求就會(huì)在亞代理處停止,因?yàn)閱〈硪呀?jīng)在等待連接關(guān)閉。這種狀態(tài)會(huì)導(dǎo)致瀏覽器一直處于掛起狀態(tài),直到客戶端或服務(wù)器之中一個(gè)連接超時(shí),關(guān)閉連接為止,一段美好的牽手就這么沒(méi)了(啞代理就是把內(nèi)容原封不動(dòng)的轉(zhuǎn)發(fā)到代理)。

為了避免這種情況,現(xiàn)代的代理是不會(huì)轉(zhuǎn)發(fā)connection:keep-alive這個(gè)首部的。
為了防止這個(gè)問(wèn)題,網(wǎng)景提出了一個(gè)方案,采用插入Proxy-connection的方式,上圖:

image.png
這個(gè)方案如何解決問(wèn)題:
    1. 首先客戶端發(fā)送Proxy-connection首部請(qǐng)求
      這是一個(gè)非標(biāo)準(zhǔn)請(qǐng)求,也就是說(shuō)即使服務(wù)器接收到這個(gè)首部也不知道他是干什么的,在服務(wù)器眼中它只知道客戶端申請(qǐng)持久連接的首部為connection:keep-alive
    1. 啞代理的模式
      報(bào)文來(lái)到了代理的位置,啞代理的話會(huì)直接轉(zhuǎn)發(fā)請(qǐng)求不解析處理,則Proxy-connection這個(gè)首部直接被發(fā)給服務(wù)器,由于服務(wù)器不識(shí)別,所以直接忽略到這個(gè)首部,這樣服務(wù)器在返回響應(yīng)的時(shí)候便不會(huì)帶有connection:keep-alive首部,當(dāng)響應(yīng)到達(dá)客戶端的時(shí)候,客戶端發(fā)現(xiàn)響應(yīng)中沒(méi)有connection:keep-alive首部,就認(rèn)為服務(wù)器拒絕了持久連接的請(qǐng)求,也就是說(shuō)客戶端判斷服務(wù)器是否接受持久連接請(qǐng)求仍是靠響應(yīng)是否存在connection首部來(lái)進(jìn)行的。
    1. 聰明的代理的模式
      聰明的代理會(huì)對(duì)請(qǐng)求進(jìn)行解析,發(fā)現(xiàn)有 Proxy-connection這個(gè)首部的時(shí)候,便會(huì)把這個(gè)首部替換成connection:keep-alive,由于服務(wù)器只能識(shí)別connection首部,當(dāng)它發(fā)現(xiàn)有這個(gè)首部的時(shí)候,就知道客戶端進(jìn)行了持久連接請(qǐng)求,就在響應(yīng)中添加connection首部,回送給客戶端。當(dāng)客戶端收到帶有connection首部的響應(yīng)時(shí),便認(rèn)為持久連接建立成功,而正好中間的聰明的路由也可以維持持久連接,這樣整條連接就處于客戶端OK代理OK服務(wù)器OK的狀態(tài),可以繼續(xù)使用該持久連接進(jìn)行報(bào)文發(fā)送。

從上面所說(shuō)的,我覺(jué)得這個(gè)方案其實(shí)就是相當(dāng)于對(duì)中間代理的類型進(jìn)行了一次判斷。
但是這個(gè)方案只能解決中間只有一個(gè)代理的情況,如果聰明的任意一邊還存在一個(gè)啞代理,那么仍會(huì)出現(xiàn)最開始的啞代理問(wèn)題

persistent

HTTP/1.1的持久連接默認(rèn)是開啟的,只有首部中包含connection:close,才會(huì)事務(wù)結(jié)束之后關(guān)閉連接。當(dāng)然服務(wù)器和客戶端仍可以隨時(shí)關(guān)閉持久連接。

當(dāng)發(fā)送了connection:close首部之后客戶端就沒(méi)有辦法在那條連接上發(fā)送更多的請(qǐng)求了。當(dāng)然根據(jù)持久連接的特性,一定要傳輸正確的content-length。

還有根據(jù)HTTP/1.1的特性,是不應(yīng)該和HTTP/1.0客戶端建立持久連接的。最后,一定要做好重發(fā)的準(zhǔn)備。

管道化連接

HTTP/1.1允許在持久連接上使用管道,這樣就不用等待前一個(gè)請(qǐng)求的響應(yīng),直接在管道上發(fā)送第二個(gè)請(qǐng)求,在高延遲下,提高性能。

管道化連接的限制

  • 不是持久連接就不能使用管道。
  • 必須按照同樣的發(fā)送順序回送響應(yīng),因?yàn)閳?bào)文沒(méi)有標(biāo)簽,很可能就順序就亂咯。
  • 因?yàn)榭梢噪S時(shí)關(guān)閉持久連接,所以要隨時(shí)做好重發(fā)準(zhǔn)備
  • 不應(yīng)該使用管道化發(fā)送重復(fù)發(fā)送會(huì)有副作用的請(qǐng)求(如post,重復(fù)提交)。

參考文章:
https://www.cnblogs.com/littlewish/archive/2013/01/17/2865218.html

?著作權(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)容