前言
上一篇 HTTP 講到了第3章。這次我們講第4章。有太多要學(xué),不是科班出生的表示壓力有點(diǎn)大,需要趕緊學(xué),幸運(yùn)的是我現(xiàn)在這家公司每個(gè)人我都能在他們身上學(xué)到東西。
TCP 是啥
HTTP的上一層,傳輸層用的是TCP ,書中簡單的說了下TCP,建議大家還是去看看 《TCP/IP 詳解一卷》。那個(gè)說的詳細(xì)。
HTTP 事務(wù)的時(shí)延
我們發(fā)送一個(gè)請(qǐng)求,其實(shí)在服務(wù)器處理的時(shí)間一般都不長,時(shí)間上的花費(fèi)是在傳輸數(shù)據(jù)的路上。見下圖:

TCP連接的握手時(shí)延
握手需要發(fā)送三個(gè)TCP數(shù)據(jù),這些是發(fā)送HTTP數(shù)據(jù)的準(zhǔn)備工作花費(fèi)了很多時(shí)間,原本在發(fā)送3個(gè)TCP包前是不會(huì)發(fā)送HTTP請(qǐng)求的,但是后來發(fā)現(xiàn)在TCP握手的最后一個(gè)數(shù)據(jù)包可以利用發(fā)送數(shù)據(jù),這種技術(shù)叫做捎帶。請(qǐng)求就變成這個(gè)樣子:

延遲確認(rèn)
書中表面:TCP傳輸?shù)臅r(shí)候都要接收方回發(fā)一個(gè)已收到的確認(rèn)信息(確認(rèn)報(bào)文),來告訴發(fā)送方,信息已經(jīng)收到,不需要再發(fā)送。
一個(gè)確認(rèn)報(bào)文是很小的,如果單獨(dú)作為一個(gè)TCP包發(fā)送顯得太浪費(fèi),所以操作系統(tǒng)會(huì)使用延時(shí)確認(rèn)技術(shù),簡單的說就是在確認(rèn)收到信息的時(shí)候,不立馬發(fā)送確認(rèn)報(bào)文,而是等待一小段時(shí)間,等待有同地址的報(bào)文,并將其合并一起發(fā)送。類比現(xiàn)實(shí)生活很是形象。
TCP慢啟動(dòng)
簡單的說就是: 開始發(fā)送TCP請(qǐng)求時(shí)不會(huì)立馬發(fā)送多個(gè)TCP報(bào)文,而是慢慢的并行的發(fā)送數(shù)量。比如成功發(fā)送一個(gè)之后,一次發(fā)送兩個(gè),兩個(gè)成功之后。。。這樣是有好處的,比如可以避免多個(gè)TCP報(bào)文因?yàn)橥粋€(gè)原因發(fā)送失敗的而引發(fā)的性能浪費(fèi)。
Connection
- 以上簡單的說了下TCP,我想看HTTP權(quán)威指南也不知道他想表達(dá)啥。建議看 TCP/IP詳解來了解TCP 這塊吧,后期我會(huì)邊玩我的MAC ,邊看書邊學(xué)這本書。
Connection 是HTTP的一個(gè)首部字段。
特點(diǎn)一:在Connection中包含的字段,不能被轉(zhuǎn)出到下一個(gè)地址。比如 Connection: name .那么name 這個(gè)首部就只能到下一個(gè)地址,活不到被下一個(gè)轉(zhuǎn)出。
請(qǐng)求方式
下面我們來聊聊web怎么玩HTTP
串行
這是最原始的時(shí)代,估計(jì)比我還老。這種方式就是發(fā)送一個(gè)HTTP請(qǐng)求等其全部完成之后再發(fā)送下一個(gè)請(qǐng)求。(stupid)
直接上圖吧,不嗶嗶:

并行
誰動(dòng)能行到能并行,計(jì)算機(jī)本來就用的特性。
上例??的情況,我們分析,可以發(fā)現(xiàn),1. 一次只發(fā)一個(gè)請(qǐng)求,浪費(fèi)帶寬。2. 事務(wù)之間的聯(lián)系不一定要有先后關(guān)系,可以同時(shí)請(qǐng)求相互不影響。
模型圖:( 書中給的例子是一個(gè)HTML 和 3個(gè)圖片)

并行的問題:
- 帶寬可能有限,帶寬讓我們不可能高效的并行多個(gè)請(qǐng)求。
- 性能,切換進(jìn)程是需要花費(fèi)性能的。
- 服務(wù)器拒絕,你的機(jī)子牛逼了,服務(wù)器不干了。大家都一次發(fā)這么多請(qǐng)求,服務(wù)器撐不住的。你慢點(diǎn)。??
持久連接
并行連接其實(shí)并沒有本質(zhì)的提高連接的速度。它只是利用了計(jì)算機(jī)的進(jìn)程功能,并沒有利用網(wǎng)絡(luò)知識(shí)。
非持續(xù)連接的問題:每次完成HTTP請(qǐng)求之后都要關(guān)閉TCP連接,但是我們的網(wǎng)站可能對(duì)同一個(gè)服務(wù)器發(fā)送多個(gè)請(qǐng)求,所以花費(fèi)了很多時(shí)間在開啟關(guān)閉TCP連接的過程中。
HTTP1.1 就通過網(wǎng)絡(luò)知識(shí)本質(zhì)的提升了性能。
持續(xù)連接:在一個(gè)HTTP請(qǐng)求完成之后一段時(shí)間內(nèi)不關(guān)閉TCP的連接。
HTTP持久連接解決的問題:
- 減少建立TCP連接的時(shí)延
- 減少慢啟動(dòng)的時(shí)延
上圖:

http1.0 持久連接 - Keep-alive
http1.0 如果想使用持久連接,會(huì)在請(qǐng)求報(bào)文中加入 Connection:keep-Alive ,如果服務(wù)器同意就會(huì)回發(fā)Connection:keep-alive .
一般 Connection:keep-alive 會(huì)和 keep-alive 首部一起使用 。如
Connection: Keep-Alive
Keep-Alive: max=5, timeout=120 ### 服務(wù)器還能支持保留多少個(gè)連接, 希望保持120秒的連接
keep-alive 的規(guī)則與限制
- 持久連接建立起來之后,如果在這條連接上沒有在繼續(xù)發(fā) Connection:Keep-Alive 那么持久連接就會(huì)斷開。
- 實(shí)體的主題部分必須代用正確的Content-Length,這樣就能讓另一端知道是報(bào)文的結(jié)束還是新報(bào)文的開始。
占坑不是太懂 - 啞代理問題
啞代理
啞代理的問題會(huì)出現(xiàn)在我們的網(wǎng)絡(luò)路線中出現(xiàn)一個(gè)不懂Keep-Alive機(jī)制又盲目轉(zhuǎn)發(fā)的代理的情況。
首先我們主機(jī)發(fā)送一份Keep-Alive的報(bào)文,代理接受到這樣一份報(bào)文,它不懂客戶端要保持連接,然后又轉(zhuǎn)發(fā)請(qǐng)求給服務(wù)器,服務(wù)器懂啊,就回了一份Connection:Keep-Alive的報(bào)文表示同意保持連接,中間代理又接受到了這樣的報(bào)文,還是不懂啊,再轉(zhuǎn)發(fā)給客戶端。這是客戶端和服務(wù)端都懂對(duì)方??。那么客戶端下一次就不會(huì)再發(fā)TCP握手?jǐn)?shù)據(jù)啦,直接發(fā)請(qǐng)求。但是這時(shí)代理就不干了,你不發(fā)建立連接的請(qǐng)求,不符合規(guī)矩,直接無視。尷尬的啞代理情況就出現(xiàn)了。
這種尷尬的情況書中沒有給出完備的解決方案。
HTTP1.1 默認(rèn)持續(xù)連接
HTTP1.1 持久連接的規(guī)章制度
- HTTP1.1 不用發(fā)送Connection:keep-Alive 也是持久連接的
- 只有在發(fā)送Connection: close 時(shí)才能斷開持久連接
- 實(shí)體主體部分的長度與相應(yīng)的Content-Length一致,或者使用分塊出函數(shù)編碼方式。連接才能持久保持。
占坑 - HTTP1.1 代理必須能夠分別管理客戶端和服務(wù)器的持久連接
- 一個(gè)客戶端最多只能與服務(wù)器或代理保持最多兩個(gè)持久連接
管道化連接
管道化在我的理解就是并行版的持久化連接請(qǐng)求。
就是在建立持久化連接后,在不等待上一條請(qǐng)求成功返回前就發(fā)送下一條請(qǐng)求。就是這么簡單。
上圖:

書中說了4點(diǎn)管道化的注意事項(xiàng),但我感覺太過啰嗦,都是些開發(fā)者自己應(yīng)該注意的問題,不在我們的知識(shí)學(xué)習(xí)范圍內(nèi)不說了。
關(guān)于關(guān)閉連接
書中建議我們不適用管道化來發(fā)一些非冪等的請(qǐng)求,因?yàn)槿绻虚g斷開了很難判斷是否服務(wù)端處理了請(qǐng)求,還是還沒收到就已經(jīng)斷開了連接。
記錄生活
我又戀愛了,又是那個(gè)女孩。異地戀。反而讓我覺得我應(yīng)該更快的成熟。原本想著畢業(yè)第一年好好的善待自己,看來還是要規(guī)劃下那少的可憐的薪水。