HTTP 1.0
問題
- 性能問題贸辈,連接的建立惋鸥、關(guān)閉都是耗時操作贺嫂。
- 服務(wù)器推送問題际起,服務(wù)器無法主動向客戶端推送消息拾碌。
Keep-Alive機制和Content-Length屬性
Http 1.0設(shè)計了一個Keep-Alive機制來實現(xiàn)TCP連接的復(fù)用吐葱。客戶端在HTTP請求的頭部加上一個字段Connection:Keep-Alive校翔。服務(wù)器收到帶有這樣字段的請求弟跑,在處理完請求之后不會關(guān)閉連接,同時在HTTP的Response里面也會加上該字段防症,然后等待客戶端在該連接上發(fā)送下一個請求孟辑。服務(wù)端會有一個Keep-Alive timeout參數(shù),過一段時間之后告希,如果該連接上沒有新的請求進來扑浸,該連接就會關(guān)閉烧给。以前一個連接就只發(fā)送一個請求燕偶,返回一個響應(yīng),處理完畢础嫡,把連接關(guān)閉指么,客戶端就知道請求處理結(jié)束了。現(xiàn)在是在HTTP Response的頭部榴鼎,返回了一個Content-Length:xx的字段伯诬,這個字段可以告訴客戶端Response的body公有多少個字節(jié),額可兌換接收到這么多個字節(jié)之后巫财,就知道響應(yīng)成功接收完畢盗似。
HTTP 1.1
連接復(fù)用與chunk機制
默認(rèn)連接復(fù)用,除非在請求頭上加上connection:close平项。引入chunk機制(http streaming)赫舒。在響應(yīng)的頭部加上Transfer-Encoding:chunked屬性。其目的是告訴客戶端闽瓢,響應(yīng)的body是分成一塊塊的接癌,塊與塊之間有間隔符,所有塊的結(jié)尾有特殊標(biāo)記扣讼,這樣缺猛,就算沒有Content-Length字段,也能方便客戶端判斷出響應(yīng)的末尾椭符。
pipeline和隊頭阻塞
pipeline有個致命問題荔燎,Head-of-Line Blocking,隊頭阻塞销钝∮凶桑客戶單接收響應(yīng)的順序必須和發(fā)送的順序一致,這樣如果前面的響應(yīng)延時了曙搬,后續(xù)的響應(yīng)也會阻塞摔吏。也正因為如此鸽嫂,為了避免pipeline帶來的副作用,很多瀏覽器默認(rèn)把pipeline關(guān)閉了征讲。
HTTP/2前的性能提升方法
- Spriting技術(shù):專門針對小圖片据某,將小圖拼成大圖,到了瀏覽器诗箍,再進行截取顯示癣籽。減少http請求數(shù)
- 內(nèi)聯(lián)(Inlining):將圖片的原始數(shù)據(jù)嵌入css文件中
- js拼接:大量小js合并成一個文件并壓縮
- 請求分片:多做幾個域名,繞開瀏覽器限制
服務(wù)器主動推送問題解決
- 客戶端定期輪詢
- flashSocket滤祖、WebSocket
- HTTP長輪詢:服務(wù)器端夯住請求連接筷狼,過時間關(guān)閉,變相用HTTP實現(xiàn)了TCP的長連接效果匠童,最常用的服務(wù)器端推送方法
- HTTP Streaming:服務(wù)端利用Transfer-Encoding:chunked機制埂材,發(fā)送一個沒完沒了的chunk流,就一個連接汤求,但其Response永遠接收不完俏险。
HTTP/2
HTTP/2和Http1.1并不是平級的位置,而是處在HTTP1.1和TCP之間扬绪。
二進制分幀
每個請求和響應(yīng)實際上組成了一個邏輯上的”流“竖独,為每條流分配一個流id,把這個id作為標(biāo)簽,達到每一個幀上挤牛。這樣就是沒有了http1.1的pipeline限制莹痢,響應(yīng)可以亂序返回。
二進制分幀并沒有徹底解決pipeline的”隊頭阻塞“問題墓赴,只是從HTTP Request粒度細(xì)化到了”幀“粒度竞膳。
頭部壓縮
HTTPS
對稱加密的問題
秘鑰的傳輸和存儲存在問題。
雙向非對稱加密
在這個過程中竣蹦,存在著簽名和驗簽與加密和解密兩個過程:
1.簽名和驗簽顶猜。私鑰簽名,公鑰驗簽痘括,目的是防篡改长窄。如果第三方截取到信息之后篡改,則接收方驗簽肯定過不了纲菌。同時也防抵賴挠日,既然沒有人可篡改,只可能是發(fā)送方自己發(fā)出的翰舌。
2.加密和解密嚣潜。公鑰加密,私鑰解密椅贱。目的是防止信息被第三方攔截和偷聽懂算。第三方即便能截獲到信息只冻,但如果沒有私鑰,也解密不了计技。
在雙向非對稱加密中喜德,客戶端需要提前知道服務(wù)器的公鑰,服務(wù)器需要知道客戶端的公鑰垮媒,和對稱加密一樣舍悯,同樣面臨公鑰如何傳輸?shù)膯栴}。
單向非對稱加密
中間人攻擊
通過分析可以發(fā)現(xiàn)睡雇,我們并不需要雙向的非對稱加密萌衬,而用單向的非對稱加密就能達到傳輸?shù)哪康摹5珶o論是單向還是雙向它抱,都存在著公鑰如何被安全傳輸?shù)膯栴}秕豫。
客戶端和服務(wù)器端都以為自己是在和對方通信,但其實他們都是在和中間人C通信抗愁。需要想個辦法證明服務(wù)器收到的公鑰馁蒂,的確就是客戶端發(fā)出的呵晚,中間沒人可以篡改公鑰蜘腌,反過來也是一樣的。
數(shù)字證書和證書認(rèn)證中心
引入一個中間機構(gòu)CA饵隙。當(dāng)服務(wù)器把公鑰發(fā)給客戶端時撮珠,不是直接發(fā)送公鑰,而是發(fā)送公鑰對應(yīng)的證書金矛。服務(wù)器先把自己的公鑰發(fā)送CA芯急,CA給服務(wù)器頒發(fā)一個數(shù)字證書(Certificate),這個證書相當(dāng)于服務(wù)器的身份證驶俊。之后娶耍,服務(wù)器把證書給客戶端,客戶端可以驗證證書是否為服務(wù)器下發(fā)的饼酿。
根證書和CA信任鏈
SSL/TLS四次握手
在建立TCP連接之后榕酒,數(shù)據(jù)發(fā)送之前,SSL/TLS協(xié)議通過四次握手故俐、兩個來回想鹰,協(xié)商出客戶端和服務(wù)器之間的對稱加密秘鑰。第一個來回药版,是公鑰的傳輸與驗證過程(通過數(shù)字證書)辑舷;第二個來回基于第一個來回得到的公鑰,協(xié)商出對稱加密的秘鑰槽片。接下來何缓,就是正常的應(yīng)用層數(shù)據(jù)包的發(fā)送操作了肢础。為了協(xié)商出對稱加密的秘鑰,引入了幾個隨機數(shù)碌廓。
HTTPS過程
https主要解決安全問題乔妈,http/2主要解決性能問題。
TCP
- 解決不丟問題:ACK+重發(fā)氓皱。服務(wù)器每次收到一個包路召,就要對客戶端進行確認(rèn),反饋給客戶單已經(jīng)收到了數(shù)據(jù)包波材;如果客戶端在超時時間內(nèi)沒有收到ACK股淡,則重發(fā)數(shù)據(jù)。
- 解決不重的問題廷区,順序ACK唯灵,例如,服務(wù)器給客戶端回復(fù)ACK=6隙轻,意思是所有小于或等于6的數(shù)據(jù)包全部收到了埠帕,之后凡是再收到這個范圍的數(shù)據(jù)包,則判定為重復(fù)的包玖绿,丟棄即可敛瓷。
*解決時序錯亂問題,服務(wù)器雖然接收數(shù)據(jù)包是并發(fā)的斑匪,但數(shù)據(jù)包的ACK是按照編號從小到大注意確認(rèn)的呐籽,所以數(shù)據(jù)包的時序是有保證的。
總之蚀瘸,TCP通過ACK+重發(fā)+數(shù)據(jù)包順序確認(rèn)解決了丟包狡蝶,亂序,重復(fù)的問題贮勃。
TCP的假連接(狀態(tài)機)
為什么開始是處于CLOSED狀態(tài)贪惹,而沒有一個INT(初始)狀態(tài)?是因為連接是復(fù)用的寂嘉,每個連接用4元組唯一表示奏瞬,關(guān)閉之后,后面又會開啟垫释,所以沒有必要引入”初始“狀態(tài)丝格。
三次握手
四次揮手
TIME_WAIT狀態(tài)存在的原因:
- close后,仍可能有數(shù)據(jù)包還在網(wǎng)絡(luò)上”閑逛“棵譬,此時如果收到了這些數(shù)據(jù)包显蝌,可能會導(dǎo)致連接重開。4元組無法區(qū)分新老連接,導(dǎo)致之前的數(shù)據(jù)包在新連接打開后被當(dāng)做新的數(shù)據(jù)包曼尊。老連接上的數(shù)據(jù)包會”串“到新連接上面酬诀,不可接受。任何一個IP數(shù)據(jù)包在網(wǎng)絡(luò)上逗留的最長時間是MSL骆撇,這個值默認(rèn)是120s瞒御。一個連接保持在TIME_WAIT狀態(tài)后2xMSL后會進入CLOSE。
- 第四次發(fā)送的數(shù)據(jù)包神郊,服務(wù)器是否收到是不確定的肴裙。可能會重新發(fā)送第三次的數(shù)據(jù)包涌乳,然后再次發(fā)送第四次的數(shù)據(jù)包蜻懦,第三次和第四次數(shù)據(jù)包的時間和,最長是兩個MSL夕晓,所以客戶端在TIME_WAIT狀態(tài)等待2xMSL時間宛乃。
產(chǎn)生的問題:
一個連接并不是想關(guān)就能立刻關(guān)的,關(guān)閉后還要等2xMSL時間才能重開蒸辆,這就會造成一個問題征炼,如果頻繁地創(chuàng)建連接,最后可能導(dǎo)致大量的連接處于TIME_WAIT狀態(tài)躬贡,最終耗光所有的連接資源谆奥。為了避免這種問題,可以采取如下措施: - 不要讓服務(wù)器主動關(guān)閉連接逗宜。這樣服務(wù)器的連接就不會處于TIME_WAIT狀態(tài)雄右。
- 客戶端做連接池,復(fù)用連接纺讲,而不要頻繁的創(chuàng)建和關(guān)閉。這其實也是HTTP1.1和HTTP/2采用的思路囤屹。
QUIC
略