Keep-alive首部只會對這條離開客戶端的TCP鏈路產(chǎn)生影響;如果一臺客戶端正在與一臺服務(wù)器對話掘而,客戶端可以發(fā)送一個Connection:Keep-alive首部來告訴服務(wù)器嚼吞,它希望保持持久連接丑搔;如果服務(wù)器支持Keep-alive,就在響應(yīng)中存在一個Connection:Keep-alive首部狂男。
1. Connection首部和盲中繼
在代理中埠忘,它們不理解Connection首部脾拆,而且不理解在沿著轉(zhuǎn)發(fā)鏈路將其發(fā)送出去之前,應(yīng)該將該首部刪除莹妒,不會對Connection首部進(jìn)行特殊處理名船。
假設(shè)一個Web應(yīng)用程序正通過一個盲中繼的啞代理與Web服務(wù)器進(jìn)行通信。如下所示
(a). Web應(yīng)用程序向代理發(fā)送了一條報文动羽,其中包含了Connection: Keep-alive首部包帚;客戶端請求建立一條Keep-alive連接渔期,需要等待響應(yīng)运吓,以確定對象是否可它對Keep-alive信道的請求。
(b). 啞代理收到了這個請求疯趟,但它并不理解Connection首部(只是將其作為一個擴(kuò)展首部對待)拘哨,因此,將報文一字不漏發(fā)送給服務(wù)器信峻。但Connection首部是個逐跳首部倦青,只適用于單條傳輸鏈路,報文在傳輸?shù)酱頃r盹舞,應(yīng)該得到處理产镐,不應(yīng)該沿著傳輸向下傳輸。
(c).在服務(wù)器端收到這條請求后踢步,會以為是代理希望進(jìn)行Keep-alive對話癣亚。對于服務(wù)器來說這沒有問題,它同意了對話获印,并回送一個Connection:Keep-alive響應(yīng)首部述雾。因此,服務(wù)器會認(rèn)為與代理進(jìn)行Keep-alive對話兼丰,遵循Keep-alive規(guī)則玻孟。但代理對此一無所知。
(d). 啞代理將服務(wù)器的響應(yīng)報文回送給客戶端鳍征,并將響應(yīng)Connection:Keep-alive首部(不處理)一起發(fā)送回去黍翎。
(e). 客戶端收到這個首部后,就會認(rèn)為服務(wù)器同意Keep-alive對話艳丛。實際情況是:服務(wù)器與代理建立Keep-alive對話玩敏,但代理(不會產(chǎn)生請求)一無所知斗忌;客戶端以為已經(jīng)與服務(wù)器建立了對話,其實這個鏈路在代理與服務(wù)器之間建立旺聚。當(dāng)客戶端繼續(xù)發(fā)送請求時织阳,請求被忽略,因為同一連接(數(shù)據(jù)必須由代理--源端點 產(chǎn)生)上會有其他請求砰粹。
后果:這種錯誤的通信方式會使客戶端處于掛起狀態(tài)唧躲,直到客戶端或服務(wù)器將連接超時,并將其關(guān)閉碱璃。
2. 代理和逐跳首部
為了避免上述問題弄痹,現(xiàn)代代理都不轉(zhuǎn)發(fā)Connection首部和所有Connection值中的首部。
插入Proxy-Connection
在不要求所有Web應(yīng)用程序支持高版本HTTP(HTTP/1.1以上)嵌器,網(wǎng)景提出一個對盲中繼問題的變通方法肛真。雖然解決在客戶端后面緊跟著一個盲中繼所帶來的問題,但并沒有解決所有其他情況下的問題爽航。
問題:是由啞代理盲目地轉(zhuǎn)發(fā)Connection:Keep-alive之類的逐跳首部惹出的麻煩蚓让。逐跳首部只與一條特定的連接有關(guān),不能被轉(zhuǎn)發(fā)讥珍。當(dāng)下游服務(wù)器將轉(zhuǎn)發(fā)來的Connection首部作為來自代理(源)自身請求時历极,就會引起問題。
網(wǎng)景的變通方法是:瀏覽器會向代理發(fā)送非標(biāo)準(zhǔn)的Proxy-Connection擴(kuò)展首部衷佃,而不是官方支持的Connection首部趟卸。如果是盲中繼,它會將無意的Proxy-Connection首部轉(zhuǎn)發(fā)給服務(wù)器氏义,服務(wù)器會忽略此首部锄列,不會產(chǎn)生任何問題。
如果是一個聰明的代理(能夠理解持久連接的握手動作)惯悠,會將Connection首部取代Proxy-Connection首部邻邮,后將其發(fā)送給服務(wù)器。
如果只有一個代理時吮螺,可以用這種方法解決這個問題饶囚,但在啞代理任意一側(cè)有一個聰明代理時,這個問題會再次露頭鸠补。
HTTTP/1.1持久連接
HTTP/1.1逐漸停止了對Keep-alive連接的支持萝风,用一種名為持久連接的改進(jìn)型來取代它。
在所有的連接中默認(rèn)情況是持久連接的紫岩,會在事務(wù)處理結(jié)束之后规惰,或承諾時間之內(nèi)將其關(guān)閉。要顯式地關(guān)閉這個持久連接泉蝌,需要在報文中加入Connection: close首部歇万。而在之前HTTP版本中揩晴,Keep-alive連接是可選的,要不就不支持贪磺。
HTTP/1.1客戶端收到響應(yīng)后硫兰,除非報文中存在Connection:close首部,不然HTTP/1.1持久連接將維持打開狀態(tài)寒锚。但是劫映,客戶端或服務(wù)器依然可以隨時關(guān)閉這個持久連接,即使沒有接到報文或報文中沒有Connection:colse首部刹前。
持久連接的限制和規(guī)則
- 發(fā)送了Connection: close請求首部之后泳赋,客戶端將無法在這種連接發(fā)送請求(代理將忽略,除非再次握手)喇喉。
- 建立持久連接的條件: 報文的實體主體部分的長度和相應(yīng)的Content-Length值一致祖今,代理或服務(wù)器才能知道一個事務(wù)的結(jié)束和另一個事務(wù)的開始。
- 不建議HTTP/1.1服務(wù)器與HTTP/1.0客戶端建立持久連接拣技,實際還存在這種情況千诬。
- HTTP/1.1設(shè)備可以在任意時刻關(guān)閉連接。
- 在異常的關(guān)閉連接后过咬,HTTP/1.1應(yīng)用程序能夠從關(guān)閉中恢復(fù)出來大渤,只要不存在可能的累積起來的副作用制妄。
- 一個客戶端對任何服務(wù)器或代理最多只能維護(hù)兩條連接掸绞。