在我們所處的互聯(lián)網(wǎng)世界中溺忧,HTTP協(xié)議算得上是使用最廣泛的網(wǎng)絡(luò)協(xié)議隙轻。最近http2.0的誕生使得它再次互聯(lián)網(wǎng)技術(shù)圈關(guān)注的焦點(diǎn)蛆楞。任何事物的消退和新生都有其背后推動(dòng)的力量郎笆。對(duì)于HTTP來(lái)說(shuō)冷溃,這力量復(fù)雜來(lái)說(shuō)是各種技術(shù)細(xì)節(jié)的演進(jìn)匀哄,簡(jiǎn)單來(lái)說(shuō)是用戶(hù)體驗(yàn)和感知的進(jìn)化振惰。用戶(hù)總是希望網(wǎng)絡(luò)上的信息能盡可能快的抵達(dá)眼球松申,越快越好检眯,正是這種對(duì)“快”對(duì)追逐催生了今天的http2.0凿叠。1. HTTP2.0的前世http2.0的前世是http1.0和http1.1這兩兄弟涩笤。雖然之前僅僅只有兩個(gè)版本,但這兩個(gè)版本所包含的協(xié)議規(guī)范之龐大盒件,足以讓任何一個(gè)有經(jīng)驗(yàn)的工程師為之頭疼蹬碧。http1.0誕生于1996年,協(xié)議文檔足足60頁(yè)炒刁。之后第三年恩沽,http1.1也隨之出生,協(xié)議文檔膨脹到了176頁(yè)翔始。不過(guò)和我們手機(jī)端app升級(jí)不同的是罗心,網(wǎng)絡(luò)協(xié)議新版本并不會(huì)馬上取代舊版本里伯。實(shí)際上,1.0和1.1在之后很長(zhǎng)的一段時(shí)間內(nèi)一直并存渤闷,這是由于網(wǎng)絡(luò)基礎(chǔ)設(shè)施更新緩慢所決定的疾瓮。今天的http2.0也是一樣,新版協(xié)議再好也需要業(yè)界的產(chǎn)品錘煉肤晓,需要基礎(chǔ)設(shè)施逐年累月的升級(jí)換代才能普及爷贫。
1.1 HTTP站在TCP之上理解http協(xié)議之前一定要對(duì)TCP有一定基礎(chǔ)的了解。HTTP是建立在TCP協(xié)議之上补憾,TCP協(xié)議作為傳輸層協(xié)議其實(shí)離應(yīng)用層并不遠(yuǎn)漫萄。HTTP協(xié)議的瓶頸及其優(yōu)化技巧都是基于TCP協(xié)議本身的特性。比如TCP建立連接時(shí)三次握手有1.5個(gè)RTT(round-trip time)的延遲盈匾,為了避免每次請(qǐng)求的都經(jīng)歷握手帶來(lái)的延遲腾务,應(yīng)用層會(huì)選擇不同策略的http長(zhǎng)鏈接方案。又比如TCP在建立連接的初期有慢啟動(dòng)(slow start)的特性削饵,所以連接的重用總是比新建連接性能要好岩瘦。
1.1 HTTP應(yīng)用場(chǎng)景http誕生之初主要是應(yīng)用于web端內(nèi)容獲取,那時(shí)候內(nèi)容還不像現(xiàn)在這樣豐富窿撬,排版也沒(méi)那么精美启昧,用戶(hù)交互的場(chǎng)景幾乎沒(méi)有。對(duì)于這種簡(jiǎn)單的獲取網(wǎng)頁(yè)內(nèi)容的場(chǎng)景劈伴,http表現(xiàn)得還算不錯(cuò)密末。但隨著互聯(lián)網(wǎng)的發(fā)展和web2.0的誕生,更多的內(nèi)容開(kāi)始被展示(更多的圖片文件)跛璧,排版變得更精美(更多的css)严里,更復(fù)雜的交互也被引入(更多的js)。用戶(hù)打開(kāi)一個(gè)網(wǎng)站首頁(yè)所加載的數(shù)據(jù)總量和請(qǐng)求的個(gè)數(shù)也在不斷增加追城。今天絕大部分的門(mén)戶(hù)網(wǎng)站首頁(yè)大小都會(huì)超過(guò)2M刹碾,請(qǐng)求數(shù)量可以多達(dá)100個(gè)。另一個(gè)廣泛的應(yīng)用是在移動(dòng)互聯(lián)網(wǎng)的客戶(hù)端app座柱,不同性質(zhì)的app對(duì)http的使用差異很大迷帜。對(duì)于電商類(lèi)app,加載首頁(yè)的請(qǐng)求也可能多達(dá)10多個(gè)色洞。對(duì)于微信這類(lèi)IM戏锹,http請(qǐng)求可能僅限于語(yǔ)音和圖片文件的下載,請(qǐng)求出現(xiàn)的頻率并不算高锋玲。
1.2 因?yàn)檠舆t景用,所以慢影響一個(gè)網(wǎng)絡(luò)請(qǐng)求的因素主要有兩個(gè),帶寬和延遲。今天的網(wǎng)絡(luò)基礎(chǔ)建設(shè)已經(jīng)使得帶寬得到極大的提升伞插,大部分時(shí)候都是延遲在影響響應(yīng)速度割粮。http1.0被抱怨最多的就是連接無(wú)法復(fù)用,和head of line blocking這兩個(gè)問(wèn)題媚污。理解這兩個(gè)問(wèn)題有一個(gè)十分重要的前提:客戶(hù)端是依據(jù)域名來(lái)向服務(wù)器建立連接舀瓢,一般PC端瀏覽器會(huì)針對(duì)單個(gè)域名的server同時(shí)建立6~8個(gè)連接,手機(jī)端的連接數(shù)則一般控制在4~6個(gè)耗美。顯然連接數(shù)并不是越多越好京髓,資源開(kāi)銷(xiāo)和整體延遲都會(huì)隨之增大。
連接無(wú)法復(fù)用會(huì)導(dǎo)致每次請(qǐng)求都經(jīng)歷三次握手和慢啟動(dòng)商架。三次握手在高延遲的場(chǎng)景下影響較明顯堰怨,慢啟動(dòng)則對(duì)文件類(lèi)大請(qǐng)求影響較大。
head of line blocking會(huì)導(dǎo)致帶寬無(wú)法被充分利用蛇摸,以及后續(xù)健康請(qǐng)求被阻塞备图。假設(shè)有5個(gè)請(qǐng)求同時(shí)發(fā)出,如下圖:
對(duì)于http1.0的實(shí)現(xiàn)赶袄,在第一個(gè)請(qǐng)求沒(méi)有收到回復(fù)之前揽涮,后續(xù)從應(yīng)用層發(fā)出的請(qǐng)求只能排隊(duì),請(qǐng)求2饿肺,3蒋困,4,5只能等請(qǐng)求1的response回來(lái)之后才能逐個(gè)發(fā)出敬辣。網(wǎng)絡(luò)通暢的時(shí)候性能影響不大雪标,一旦請(qǐng)求1的request因?yàn)槭裁丛驔](méi)有抵達(dá)服務(wù)器,或者response因?yàn)榫W(wǎng)絡(luò)阻塞沒(méi)有及時(shí)返回购岗,影響的就是所有后續(xù)請(qǐng)求汰聋,問(wèn)題就變得比較嚴(yán)重了门粪。
1.3 解決連接無(wú)法復(fù)用http1.0協(xié)議頭里可以設(shè)置Connection:Keep-Alive喊积。在header里設(shè)置Keep-Alive可以在一定時(shí)間內(nèi)復(fù)用連接,具體復(fù)用時(shí)間的長(zhǎng)短可以由服務(wù)器控制玄妈,一般在15s左右乾吻。到http1.1之后Connection的默認(rèn)值就是Keep-Alive,如果要關(guān)閉連接復(fù)用需要顯式的設(shè)置Connection:Close拟蜻。一段時(shí)間內(nèi)的連接復(fù)用對(duì)PC端瀏覽器的體驗(yàn)幫助很大绎签,因?yàn)榇蟛糠值恼?qǐng)求在集中在一小段時(shí)間以?xún)?nèi)。但對(duì)移動(dòng)app來(lái)說(shuō)酝锅,成效不大诡必,app端的請(qǐng)求比較分散且時(shí)間跨度相對(duì)較大。所以移動(dòng)端app一般會(huì)從應(yīng)用層尋求其它解決方案,長(zhǎng)連接方案或者偽長(zhǎng)連接方案:
方案一:基于tcp的長(zhǎng)鏈接現(xiàn)在越來(lái)越多的移動(dòng)端app都會(huì)建立一條自己的長(zhǎng)鏈接通道爸舒,通道的實(shí)現(xiàn)是基于tcp協(xié)議蟋字。基于tcp的socket編程技術(shù)難度相對(duì)復(fù)雜很多扭勉,而且需要自己制定協(xié)議鹊奖,但帶來(lái)的回報(bào)也很大。信息的上報(bào)和推送變得更及時(shí)涂炎,在請(qǐng)求量爆發(fā)的時(shí)間點(diǎn)還能減輕服務(wù)器壓力(http短連接模式會(huì)頻繁的創(chuàng)建和銷(xiāo)毀連接)忠聚。不止是IM app有這樣的通道,像淘寶這類(lèi)電商類(lèi)app都有自己的專(zhuān)屬長(zhǎng)連接通道了〕罚現(xiàn)在業(yè)界也有不少成熟的方案可供選擇了两蟀,google的protobuf就是其中之一。
方案二:http long-pollinglong-polling可以用下圖表示:
客戶(hù)端在初始狀態(tài)就會(huì)發(fā)送一個(gè)polling請(qǐng)求到服務(wù)器震缭,服務(wù)器并不會(huì)馬上返回業(yè)務(wù)數(shù)據(jù)垫竞,而是等待有新的業(yè)務(wù)數(shù)據(jù)產(chǎn)生的時(shí)候再返回。所以連接會(huì)一直被保持蛀序,一旦結(jié)束馬上又會(huì)發(fā)起一個(gè)新的polling請(qǐng)求欢瞪,如此反復(fù),所以一直會(huì)有一個(gè)連接被保持徐裸。服務(wù)器有新的內(nèi)容產(chǎn)生的時(shí)候遣鼓,并不需要等待客戶(hù)端建立一個(gè)新的連接。做法雖然簡(jiǎn)單重贺,但有些難題需要攻克才能實(shí)現(xiàn)穩(wěn)定可靠的業(yè)務(wù)框架:
和傳統(tǒng)的http短鏈接相比骑祟,長(zhǎng)連接會(huì)在用戶(hù)增長(zhǎng)的時(shí)候極大的增加服務(wù)器壓力
移動(dòng)端網(wǎng)絡(luò)環(huán)境復(fù)雜,像wifi和4g的網(wǎng)絡(luò)切換气笙,進(jìn)電梯導(dǎo)致網(wǎng)絡(luò)臨時(shí)斷掉等次企,這些場(chǎng)景都需要考慮怎么重建健康的連接通道。
這種polling的方式穩(wěn)定性并不好潜圃,需要做好數(shù)據(jù)可靠性的保證缸棵,比如重發(fā)和ack機(jī)制。
polling的response有可能會(huì)被中間代理cache住谭期,要處理好業(yè)務(wù)數(shù)據(jù)的過(guò)期機(jī)制堵第。
long-polling方式還有一些缺點(diǎn)是無(wú)法克服的,比如每次新的請(qǐng)求都會(huì)帶上重復(fù)的header信息隧出,還有數(shù)據(jù)通道是單向的踏志,主動(dòng)權(quán)掌握在server這邊胀瞪,客戶(hù)端有新的業(yè)務(wù)請(qǐng)求的時(shí)候無(wú)法及時(shí)傳送针余。
方案三:http streaminghttp streaming流程大致如下:
同long-polling不同的是,server并不會(huì)結(jié)束初始的streaming請(qǐng)求,而是持續(xù)的通過(guò)這個(gè)通道返回最新的業(yè)務(wù)數(shù)據(jù)圆雁。顯然這個(gè)數(shù)據(jù)通道也是單向的傍妒。streaming是通過(guò)在server response的頭部里增加”Transfer Encoding: chunked”來(lái)告訴客戶(hù)端后續(xù)還會(huì)有新的數(shù)據(jù)到來(lái)。除了和long-polling相同的難點(diǎn)之外摸柄,streaming還有幾個(gè)缺陷:
有些代理服務(wù)器會(huì)等待服務(wù)器的response結(jié)束之后才會(huì)將結(jié)果推送到請(qǐng)求客戶(hù)端颤练。對(duì)于streaming這種永遠(yuǎn)不會(huì)結(jié)束的方式來(lái)說(shuō),客戶(hù)端就會(huì)一直處于等待response的過(guò)程中驱负。
業(yè)務(wù)數(shù)據(jù)無(wú)法按照請(qǐng)求來(lái)做分割嗦玖,所以客戶(hù)端沒(méi)收到一塊數(shù)據(jù)都需要自己做協(xié)議解析,也就是說(shuō)要做自己的協(xié)議定制跃脊。
streaming不會(huì)產(chǎn)生重復(fù)的header數(shù)據(jù)宇挫。
方案四:web socketWebSocket和傳統(tǒng)的tcp socket連接相似,也是基于tcp協(xié)議酪术,提供雙向的數(shù)據(jù)通道器瘪。WebSocket優(yōu)勢(shì)在于提供了message的概念,比基于字節(jié)流的tcp socket使用更簡(jiǎn)單绘雁,同時(shí)又提供了傳統(tǒng)的http所缺少的長(zhǎng)連接功能橡疼。不過(guò)WebSocket相對(duì)較新,2010年才起草庐舟,并不是所有的瀏覽器都提供了支持欣除。各大瀏覽器廠(chǎng)商最新的版本都提供了支持。
1.4 解決head of line blockingHead of line blocking(以下簡(jiǎn)稱(chēng)為holb)是http2.0之前網(wǎng)絡(luò)體驗(yàn)的最大禍源挪略。正如圖1中所示历帚,健康的請(qǐng)求會(huì)被不健康的請(qǐng)求影響,而且這種體驗(yàn)的損耗受網(wǎng)絡(luò)環(huán)境影響杠娱,出現(xiàn)隨機(jī)且難以監(jiān)控挽牢。為了解決holb帶來(lái)的延遲,協(xié)議設(shè)計(jì)者設(shè)計(jì)了一種新的pipelining機(jī)制摊求。
http pipeliningpipelining的流程圖可以用下圖表示:
和圖一相比最大的差別是禽拔,請(qǐng)求2,3睹簇,4奏赘,5不用等請(qǐng)求1的response返回之后才發(fā)出寥闪,而是幾乎在同一時(shí)間把request發(fā)向了服務(wù)器太惠。2,3疲憋,4凿渊,5及所有后續(xù)共用該連接的請(qǐng)求節(jié)約了等待的時(shí)間,極大的降低了整體延遲。下圖可以清晰的看出這種新機(jī)制對(duì)延遲的改變:
不過(guò)pipelining并不是救世主埃脏,它也存在不少缺陷:
pipelining只能適用于http1.1搪锣,一般來(lái)說(shuō),支持http1.1的server都要求支持pipelining彩掐。
只有冪等的請(qǐng)求(GET构舟,HEAD)能使用pipelining,非冪等請(qǐng)求比如POST不能使用堵幽,因?yàn)檎?qǐng)求之間可能會(huì)存在先后依賴(lài)關(guān)系狗超。
head of line blocking并沒(méi)有完全得到解決,server的response還是要求依次返回朴下,遵循FIFO(first in first out)原則努咐。也就是說(shuō)如果請(qǐng)求1的response沒(méi)有回來(lái),2殴胧,3渗稍,4,5的response也不會(huì)被送回來(lái)团滥。
絕大部分的http代理服務(wù)器不支持pipelining竿屹。
和不支持pipelining的老服務(wù)器協(xié)商有問(wèn)題。
可能會(huì)導(dǎo)致新的Front of queue blocking問(wèn)題灸姊。
正是因?yàn)橛羞@么多的問(wèn)題羔沙,各大瀏覽器廠(chǎng)商要么是根本就不支持pipelining,要么就是默認(rèn)關(guān)掉了pipelining機(jī)制厨钻,而且啟用的條件十分苛刻扼雏。可以參考chrome對(duì)于pipeling的問(wèn)題描述**夯膀。
1.5 其它奇技淫巧為了解決延遲帶來(lái)的苦惱诗充,永遠(yuǎn)都會(huì)有聰明的探索者找出新的捷徑來(lái)∮战ǎ互聯(lián)網(wǎng)的蓬勃興盛催生出了各種新奇技巧蝴蜓,我們來(lái)依次看下這些“捷徑”及各自的優(yōu)缺點(diǎn)。
Spriting(圖片合并)Spriting指的是將多個(gè)小圖片合并到一張大的圖片里俺猿,這樣多個(gè)小的請(qǐng)求就被合并成了一個(gè)大的圖片請(qǐng)求茎匠,然后再利用js或者css文件來(lái)取出其中的小張圖片使用。好處顯而易見(jiàn)押袍,請(qǐng)求數(shù)減少诵冒,延遲自然低。壞處是文件的粒度變大了谊惭,有時(shí)候我們可能只需要其中一張小圖汽馋,卻不得不下載整張大圖侮东,cache處理也變得麻煩,在只有一張小圖過(guò)期的情況下豹芯,為了獲得最新的版本悄雅,不得不從服務(wù)器下載完整的大圖,即使其它的小圖都沒(méi)有過(guò)期铁蹈,顯然浪費(fèi)了流量宽闲。
Inlining(內(nèi)容內(nèi)嵌)Inlining的思考角度和spriting類(lèi)似,是將額外的數(shù)據(jù)請(qǐng)求通過(guò)base64編碼之后內(nèi)嵌到一個(gè)總的文件當(dāng)中握牧。比如一個(gè)網(wǎng)頁(yè)有一張背景圖便锨,我們可以通過(guò)如下代碼嵌入:
background: url(data:image/png;base64,)
data部分是base64編碼之后的字節(jié)碼,這樣也避免了一次多余的http請(qǐng)求我碟。但這種做法也有著和spriting相同的問(wèn)題放案,資源文件被綁定到了其它文件,粒度變得難以控制矫俺。
Concatenation(文件合并)Concatenation主要是針對(duì)js這類(lèi)文件吱殉,現(xiàn)在前端開(kāi)發(fā)交互越來(lái)越多,零散的js文件也在變多厘托。將多個(gè)js文件合并到一個(gè)大的文件里在做一些壓縮處理也可以減小延遲和傳輸?shù)臄?shù)據(jù)量友雳。但同樣也面臨著粒度變大的問(wèn)題,一個(gè)小的js代碼改動(dòng)會(huì)導(dǎo)致整個(gè)js文件被下載铅匹。
Domain Sharding(域名分片)前面我提到過(guò)很重要的一點(diǎn)押赊,瀏覽器或者客戶(hù)端是根據(jù)domain(域名)來(lái)建立連接的。比如針對(duì)Example Domain**只允許同時(shí)建立2個(gè)連接包斑,但mobile.example.com被認(rèn)為是另一個(gè)域名流礁,可以再建立兩個(gè)新的連接。依次類(lèi)推罗丰,如果我再多建立幾個(gè)sub domain(子域名)神帅,那么同時(shí)可以建立的http請(qǐng)求就會(huì)更多,這就是Domain Sharding了萌抵。連接數(shù)變多之后找御,受限制的請(qǐng)求就不需要等待前面的請(qǐng)求完成才能發(fā)出了。這個(gè)技巧被大量的使用绍填,一個(gè)頗具規(guī)模的網(wǎng)頁(yè)請(qǐng)求數(shù)可以超過(guò)100霎桅,使用domain sharding之后同時(shí)建立的連接數(shù)可以多到50個(gè)甚至更多盾饮。
這么做當(dāng)然增加了系統(tǒng)資源的消耗沽一,但現(xiàn)在硬件資源升級(jí)非常之快,和用戶(hù)寶貴的等待時(shí)機(jī)相比起來(lái)實(shí)在微不足道淆两。
domain sharding還有一大好處住闯,對(duì)于資源文件來(lái)說(shuō)一般是不需要cookie的瓜浸,將這些不同的靜態(tài)資源文件分散在不同的域名服務(wù)器上澳淑,可以減小請(qǐng)求的size比原。
不過(guò)domain sharding只有在請(qǐng)求數(shù)非常之多的場(chǎng)景下才有明顯的效果插佛。而且請(qǐng)求數(shù)也不是越多越好,資源消耗是一方面量窘,另一點(diǎn)是由于tcp的slow start會(huì)導(dǎo)致每個(gè)請(qǐng)求在初期都會(huì)經(jīng)歷slow start雇寇,還有tcp 三次握手,DNS查詢(xún)的延遲蚌铜。這一部分帶來(lái)的時(shí)間損耗和請(qǐng)求排隊(duì)同樣重要锨侯,到底怎么去平衡這二者就需要取一個(gè)可靠的連接數(shù)中間值,這個(gè)值的最終確定要通過(guò)反復(fù)的測(cè)試冬殃。移動(dòng)端瀏覽器場(chǎng)景建議不要使用domain sharding囚痴,具體細(xì)節(jié)參考這篇文章**。
2. 開(kāi)拓者SPDYhttp1.0和1.1雖然存在這么多問(wèn)題审葬,業(yè)界也想出了各種優(yōu)化的手段深滚,但這些方法手段都是在嘗試?yán)@開(kāi)協(xié)議本身的缺陷,都有種隔靴搔癢涣觉,治標(biāo)不治本的感覺(jué)痴荐。直到2012年google如一聲驚雷提出了SPDY的方案,大家才開(kāi)始從正面看待和解決老版本http協(xié)議本身的問(wèn)題官册,這也直接加速了http2.0的誕生生兆。實(shí)際上,http2.0是以SPDY為原型進(jìn)行討論和標(biāo)準(zhǔn)化的膝宁。為了給http2.0讓路鸦难,google已決定在2016年不再繼續(xù)支持SPDY開(kāi)發(fā),但在http2.0出生之前员淫,SPDY已經(jīng)有了相當(dāng)規(guī)模的應(yīng)用明刷,作為一個(gè)過(guò)渡方案恐怕在還將一段時(shí)間內(nèi)繼續(xù)存在。現(xiàn)在不少app客戶(hù)端和server都已經(jīng)使用了SPDY來(lái)提升體驗(yàn)满粗,http2.0在老的設(shè)備和系統(tǒng)上還無(wú)法使用(iOS系統(tǒng)只有在iOS9+上才支持)辈末,所以可以預(yù)見(jiàn)未來(lái)幾年spdy將和http2.0共同服務(wù)的情況。
2.1 SPDY的目標(biāo)SPDY的目標(biāo)在一開(kāi)始就是瞄準(zhǔn)http1.x的痛點(diǎn)映皆,即延遲和安全性挤聘。我們上面通篇都在討論延遲,至于安全性捅彻,由于http是明文協(xié)議组去,其安全性也一直被業(yè)界詬病,不過(guò)這是另一個(gè)大的話(huà)題步淹。如果以降低延遲為目標(biāo)从隆,應(yīng)用層的http和傳輸層的tcp都是都有調(diào)整的空間诚撵,不過(guò)tcp作為更底層協(xié)議存在已達(dá)數(shù)十年之久,其實(shí)現(xiàn)已深植全球的網(wǎng)絡(luò)基礎(chǔ)設(shè)施當(dāng)中键闺,如果要?jiǎng)颖厝粋?jīng)動(dòng)骨寿烟,業(yè)界響應(yīng)度必然不高,所以SPDY的手術(shù)刀對(duì)準(zhǔn)的是http辛燥。
降低延遲筛武,客戶(hù)端的單連接單請(qǐng)求,server的FIFO響應(yīng)隊(duì)列都是延遲的大頭挎塌。
http最初設(shè)計(jì)都是客戶(hù)端發(fā)起請(qǐng)求徘六,然后server響應(yīng),server無(wú)法主動(dòng)push內(nèi)容到客戶(hù)端榴都。
壓縮http header待锈,http1.x的header越來(lái)越膨脹,cookie和user agent很容易讓header的size增至1kb大小嘴高,甚至更多竿音。而且由于http的無(wú)狀態(tài)特性,header必須每次request都重復(fù)攜帶阳惹,很浪費(fèi)流量谍失。
為了增加業(yè)界響應(yīng)的可能性,聰明的google一開(kāi)始就避開(kāi)了從傳輸層動(dòng)手莹汤,而且打算利用開(kāi)源社區(qū)的力量以提高擴(kuò)散的力度快鱼,對(duì)于協(xié)議使用者來(lái)說(shuō),也只需要在請(qǐng)求的header里設(shè)置user agent纲岭,然后在server端做好支持即可抹竹,極大的降低了部署的難度。SPDY的設(shè)計(jì)如下:
SPDY位于HTTP之下止潮,TCP和SSL之上窃判,這樣可以輕松兼容老版本的HTTP協(xié)議(將http1.x的內(nèi)容封裝成一種新的frame格式),同時(shí)可以使用已有的SSL功能喇闸。SPDY的功能可以分為基礎(chǔ)功能和高級(jí)功能兩部分袄琳,基礎(chǔ)功能默認(rèn)啟用,高級(jí)功能需要手動(dòng)啟用燃乍。
SPDY基礎(chǔ)功能多路復(fù)用(multiplexing)唆樊。多路復(fù)用通過(guò)多個(gè)請(qǐng)求stream共享一個(gè)tcp連接的方式,解決了http1.x holb(head of line blocking)的問(wèn)題刻蟹,降低了延遲同時(shí)提高了帶寬的利用率逗旁。
請(qǐng)求優(yōu)先級(jí)(request prioritization)。多路復(fù)用帶來(lái)一個(gè)新的問(wèn)題是舆瘪,在連接共享的基礎(chǔ)之上有可能會(huì)導(dǎo)致關(guān)鍵請(qǐng)求被阻塞片效。SPDY允許給每個(gè)request設(shè)置優(yōu)先級(jí)红伦,這樣重要的請(qǐng)求就會(huì)優(yōu)先得到響應(yīng)。比如瀏覽器加載首頁(yè)淀衣,首頁(yè)的html內(nèi)容應(yīng)該優(yōu)先展示昙读,之后才是各種靜態(tài)資源文件,腳本文件等加載舌缤,這樣可以保證用戶(hù)能第一時(shí)間看到網(wǎng)頁(yè)內(nèi)容箕戳。
header壓縮某残。前面提到過(guò)幾次http1.x的header很多時(shí)候都是重復(fù)多余的国撵。選擇合適的壓縮算法可以減小包的大小和數(shù)量。SPDY對(duì)header的壓縮率可以達(dá)到80%以上玻墅,低帶寬環(huán)境下效果很大介牙。
SPDY高級(jí)功能server推送(server push)。http1.x只能由客戶(hù)端發(fā)起請(qǐng)求澳厢,然后服務(wù)器被動(dòng)的發(fā)送response环础。開(kāi)啟server push之后,server通過(guò)X-Associated-Content header(X-開(kāi)頭的header都屬于非標(biāo)準(zhǔn)的剩拢,自定義header)告知客戶(hù)端會(huì)有新的內(nèi)容推送過(guò)來(lái)线得。在用戶(hù)第一次打開(kāi)網(wǎng)站首頁(yè)的時(shí)候,server將資源主動(dòng)推送過(guò)來(lái)可以極大的提升用戶(hù)體驗(yàn)徐伐。
server暗示(server hint)贯钩。和server push不同的是,server hint并不會(huì)主動(dòng)推送內(nèi)容办素,只是告訴有新的內(nèi)容產(chǎn)生角雷,內(nèi)容的下載還是需要客戶(hù)端主動(dòng)發(fā)起請(qǐng)求。server hint通過(guò)X-Subresources header來(lái)通知性穿,一般應(yīng)用場(chǎng)景是客戶(hù)端需要先查詢(xún)server狀態(tài)勺三,然后再下載資源,可以節(jié)約一次查詢(xún)請(qǐng)求需曾。
2.2 SPDY的成績(jī)SPDY的成績(jī)可以用google官方的一個(gè)數(shù)字來(lái)說(shuō)明:頁(yè)面加載時(shí)間相比于http1.x減少了64%吗坚。而且各大瀏覽器廠(chǎng)商在SPDY誕生之后的1年多里都陸續(xù)支持了SPDY,不少大廠(chǎng)app和server端框架也都將SPDY應(yīng)用到了線(xiàn)上的產(chǎn)品當(dāng)中呆万。
google的官網(wǎng)也給出了他們自己做的一份測(cè)試數(shù)據(jù)商源。測(cè)試對(duì)象是25個(gè)訪(fǎng)問(wèn)量排名靠前的網(wǎng)站首頁(yè),家用網(wǎng)絡(luò)%1的丟包率桑嘶,每個(gè)網(wǎng)站測(cè)試10次取平均值炊汹。結(jié)果如下:
不開(kāi)啟ssl的時(shí)候提升在 27% - 60%,開(kāi)啟之后為39% - 55%逃顶。 這份測(cè)試結(jié)果有兩點(diǎn)值得特別注意:
連接數(shù)的選擇連接到底是基于域名來(lái)建立讨便,還是不做區(qū)分所有子域名都共享一個(gè)連接充甚,這個(gè)策略選擇上值得商榷。google的測(cè)試結(jié)果測(cè)試了兩種方案霸褒,看結(jié)果似乎是單一連接性能高于多域名連接方式伴找。之所以出現(xiàn)這種情況是由于網(wǎng)頁(yè)所有的資源請(qǐng)求并不是同一時(shí)間發(fā)出,后續(xù)發(fā)出的子域名請(qǐng)求如果能復(fù)用之前的tcp連接當(dāng)然性能更好废菱。實(shí)際應(yīng)用場(chǎng)景下應(yīng)該也是單連接共享模式表現(xiàn)好技矮。
帶寬的影響測(cè)試基于兩種帶寬環(huán)境,一慢一快殊轴。網(wǎng)速快的環(huán)境下對(duì)減小延遲的提升更大衰倦,單連接模式下可以提升至60%。原因也比較簡(jiǎn)單旁理,帶寬越大樊零,復(fù)用連接的請(qǐng)求完成越快,由于三次握手和慢啟動(dòng)導(dǎo)致的延遲損耗就變得更明顯孽文。
出了連接模式和帶寬之外驻襟,丟包率和RTT也是需要測(cè)試的參數(shù)。SPDY對(duì)header的壓縮有80%以上芋哭,整體包大小能減少大概40%沉衣,發(fā)送的包越少,自然受丟包率影響也就越小减牺,所以丟包率大的惡劣環(huán)境下SPDY反而更能提升體驗(yàn)豌习。下圖是受丟包率影響的測(cè)試結(jié)果,丟包率超過(guò)2.5%之后就沒(méi)有提升了:
RTT越大烹植,延遲會(huì)越大斑鸦,在高RTT的場(chǎng)景下,由于SPDY的request是并發(fā)進(jìn)行的草雕,所有對(duì)包的利用率更高巷屿,反而能更明顯的減小總體延遲。測(cè)試結(jié)果如下:
SPDY從2012年誕生到2016停止維護(hù)墩虹,時(shí)間跨度對(duì)于網(wǎng)絡(luò)協(xié)議來(lái)說(shuō)其實(shí)非常之短嘱巾。如果HTTP2.0沒(méi)有出來(lái),google或許能收集到更多業(yè)界產(chǎn)品的真實(shí)反饋和數(shù)據(jù)诫钓,畢竟google自己的測(cè)試環(huán)境相對(duì)簡(jiǎn)單旬昭。但SPDY也完成了自己的使命,作為一貫扮演拓荒者角色的google應(yīng)該也早就預(yù)見(jiàn)了這樣的結(jié)局菌湃。SPDY對(duì)產(chǎn)品網(wǎng)絡(luò)體驗(yàn)的提升到底如何问拘,恐怕只有各大廠(chǎng)產(chǎn)品經(jīng)理才清楚了。
3. 救世主HTTP2.0SPDY的誕生和表現(xiàn)說(shuō)明了兩件事情:一是在現(xiàn)有互聯(lián)網(wǎng)設(shè)施基礎(chǔ)和http協(xié)議廣泛使用的前提下,是可以通過(guò)修改協(xié)議層來(lái)優(yōu)化http1.x的骤坐。二是針對(duì)http1.x的修改確實(shí)效果明顯而且業(yè)界反饋很好绪杏。正是這兩點(diǎn)讓IETF(Internet Enginerring Task Force)開(kāi)始正式考慮制定HTTP2.0的計(jì)劃,最后決定以SPDY/3為藍(lán)圖起草HTTP2.0纽绍,SPDY的部分設(shè)計(jì)人員也被邀請(qǐng)參與了HTTP2.0的設(shè)計(jì)蕾久。
3.1 HTTP2.0需要考慮的問(wèn)題HTTP2.0與SPDY的起點(diǎn)不同,SPDY可以說(shuō)是google的“玩具”拌夏,最早出現(xiàn)在自家的chrome瀏覽器和server上僧著,好不好玩以及別人會(huì)不會(huì)跟著一起玩對(duì)google來(lái)說(shuō)無(wú)關(guān)痛癢。但HTTP2.0作為業(yè)界標(biāo)準(zhǔn)還沒(méi)出生就是眾人矚目的焦點(diǎn)障簿,一開(kāi)始如果有什么瑕疵或者不兼容的問(wèn)題影響可能又是數(shù)十年之久盹愚,所以考慮的問(wèn)題和角度要非常之廣。我們來(lái)看下HTTP2.0一些重要的設(shè)計(jì)前提:
客戶(hù)端向server發(fā)送request這種基本模型不會(huì)變卷谈。
老的scheme不會(huì)變杯拐,使用http://和https://的服務(wù)和應(yīng)用不會(huì)要做任何更改霞篡,不會(huì)有http2://世蔗。
使用http1.x的客戶(hù)端和服務(wù)器可以無(wú)縫的通過(guò)代理方式轉(zhuǎn)接到http2.0上。
不識(shí)別http2.0的代理服務(wù)器可以將請(qǐng)求降級(jí)到http1.x朗兵。
因?yàn)榭蛻?hù)端和server之間在確立使用http1.x還是http2.0之前污淋,必須要要確認(rèn)對(duì)方是否支持http2.0,所以這里必須要有個(gè)協(xié)商的過(guò)程余掖。最簡(jiǎn)單的協(xié)商也要有一問(wèn)一答寸爆,客戶(hù)端問(wèn)server答,即使這種最簡(jiǎn)單的方式也多了一個(gè)RTT的延遲盐欺,我們之所以要修改http1.x就是為了降低延遲赁豆,顯然這個(gè)RTT我們是無(wú)法接受的。google制定SPDY的時(shí)候也遇到了這個(gè)問(wèn)題冗美,他們的辦法是強(qiáng)制SPDY走h(yuǎn)ttps魔种,在SSL層完成這個(gè)協(xié)商過(guò)程。ssl層的協(xié)商在http協(xié)議通信之前粉洼,所以是最適合的載體节预。google為此做了一個(gè)tls的拓展,叫NPN(Next Protocol Negotiation)属韧,從名字上也可以看出安拟,這個(gè)拓展主要目的就是為了協(xié)商下一個(gè)要使用的協(xié)議。HTTP2.0雖然也采用了相同的方式宵喂,不過(guò)HTTP2.0經(jīng)過(guò)激烈的討論糠赦,最終還是沒(méi)有強(qiáng)制HTTP2.0要走ssl層,大部分瀏覽器廠(chǎng)商(除了IE)卻只實(shí)現(xiàn)了基于https的2.0協(xié)議。HTTP2.0沒(méi)有使用NPN拙泽,而是另一個(gè)tls的拓展叫ALPN(Application Layer Protocol Negotiation)唆铐。SPDY也打算從NPN遷移到ALPN了。
各瀏覽器(除了IE)之所以只實(shí)現(xiàn)了基于SSL的HTTP2.0奔滑,另一個(gè)原因是走SSL請(qǐng)求的成功率會(huì)更高艾岂,被SSL封裝的request不會(huì)被監(jiān)聽(tīng)和修改,這樣網(wǎng)絡(luò)中間的網(wǎng)絡(luò)設(shè)備就無(wú)法基于http1.x的認(rèn)知去干涉修改request朋其,http2.0的request如果被意外的修改王浴,請(qǐng)求的成功率自然會(huì)下降。
HTTP2.0協(xié)議沒(méi)有強(qiáng)制使用SSL是因?yàn)槁?tīng)到了很多的反對(duì)聲音梅猿,畢竟https和http相比氓辣,在不優(yōu)化的前提下性能差了不少,要把https優(yōu)化到幾乎不增加延遲的程度又需要花費(fèi)不少力氣袱蚓。IETF面對(duì)這種兩難的處境做了妥協(xié)钞啸,但大部分瀏覽器廠(chǎng)商(除了IE)并不買(mǎi)帳,他們只認(rèn)https2.0喇潘。對(duì)于app開(kāi)發(fā)者來(lái)說(shuō)体斩,他們可以堅(jiān)持使用沒(méi)有ssl的http2.0,不過(guò)要承擔(dān)一個(gè)多余的RTT延遲和請(qǐng)求可能被破壞的代價(jià)颖低。
3.1 HTTP2.0主要改動(dòng)HTTP2.0作為新版協(xié)議絮吵,改動(dòng)細(xì)節(jié)必然很多,不過(guò)對(duì)應(yīng)用開(kāi)發(fā)者和服務(wù)提供商來(lái)說(shuō)忱屑,影響較大的就幾點(diǎn)蹬敲。
新的二進(jìn)制格式(Binary Format)http1.x誕生的時(shí)候是明文協(xié)議,其格式由三部分組成:start line(request line或者status line)莺戒,header伴嗡,body。要識(shí)別這3部分就要做協(xié)議解析从铲,http1.x的解析是基于文本瘪校。基于文本協(xié)議的格式解析存在天然缺陷食店,文本的表現(xiàn)形式有多樣性渣淤,要做到健壯性考慮的場(chǎng)景必然很多,二進(jìn)制則不同吉嫩,只認(rèn)0和1的組合价认。基于這種考慮http2.0的協(xié)議解析決定采用二進(jìn)制格式自娩,實(shí)現(xiàn)方便且健壯用踩。
有人可能會(huì)覺(jué)得基于文本的http調(diào)試方便很多渠退,像firebug,chrome脐彩,charles等不少工具都可以即時(shí)調(diào)試修改請(qǐng)求碎乃。實(shí)際上現(xiàn)在很多請(qǐng)求都是走h(yuǎn)ttps了,要調(diào)試https請(qǐng)求必須有私鑰才行惠奸。http2.0的絕大部分request應(yīng)該都是走h(yuǎn)ttps梅誓,所以調(diào)試方便無(wú)法作為一個(gè)有力的考慮因素了。curl佛南,tcpdump梗掰,wireshark這些工具會(huì)更適合http2.0的調(diào)試。
http2.0用binary格式定義了一個(gè)一個(gè)的frame嗅回,和http1.x的格式對(duì)比如下圖:
http2.0的格式定義更接近tcp層的方式及穗,這張二機(jī)制的方式十分高效且精簡(jiǎn)。length定義了整個(gè)frame的開(kāi)始到結(jié)束绵载,type定義frame的類(lèi)型(一共10種)埂陆,flags用bit位定義一些重要的參數(shù),stream id用作流控制娃豹,剩下的payload就是request的正文了焚虱。
雖然看上去協(xié)議的格式和http1.x完全不同了,實(shí)際上http2.0并沒(méi)有改變http1.x的語(yǔ)義培愁,只是把原來(lái)http1.x的header和body部分用frame重新封裝了一層而已著摔。調(diào)試的時(shí)候?yàn)g覽器甚至?xí)裩ttp2.0的frame自動(dòng)還原成http1.x的格式。具體的協(xié)議關(guān)系可以用下圖表示:
連接共享http2.0要解決的一大難題就是多路復(fù)用(MultiPlexing)定续,即連接共享。上面協(xié)議解析中提到的stream id就是用作連接共享機(jī)制的禾锤。一個(gè)request對(duì)應(yīng)一個(gè)stream并分配一個(gè)id私股,這樣一個(gè)連接上可以有多個(gè)stream,每個(gè)stream的frame可以隨機(jī)的混雜在一起恩掷,接收方可以根據(jù)stream id將frame再歸屬到各自不同的request里面倡鲸。
前面還提到過(guò)連接共享之后,需要優(yōu)先級(jí)和請(qǐng)求依賴(lài)的機(jī)制配合才能解決關(guān)鍵請(qǐng)求被阻塞的問(wèn)題黄娘。http2.0里的每個(gè)stream都可以設(shè)置又優(yōu)先級(jí)(Priority)和依賴(lài)(Dependency)峭状。優(yōu)先級(jí)高的stream會(huì)被server優(yōu)先處理和返回給客戶(hù)端,stream還可以依賴(lài)其它的sub streams逼争。優(yōu)先級(jí)和依賴(lài)都是可以動(dòng)態(tài)調(diào)整的优床。動(dòng)態(tài)調(diào)整在有些場(chǎng)景下很有用,假想用戶(hù)在用你的app瀏覽商品的時(shí)候誓焦,快速的滑動(dòng)到了商品列表的底部胆敞,但前面的請(qǐng)求先發(fā)出,如果不把后面的請(qǐng)求優(yōu)先級(jí)設(shè)高稻爬,用戶(hù)當(dāng)前瀏覽的圖片要到最后才能下載完成掖棉,顯然體驗(yàn)沒(méi)有設(shè)置優(yōu)先級(jí)好。同理依賴(lài)在有些場(chǎng)景下也有妙用龟劲。
header壓縮前面提到過(guò)http1.x的header由于cookie和user agent很容易膨脹观话,而且每次都要重復(fù)發(fā)送予借。http2.0使用encoder來(lái)減少需要傳輸?shù)膆eader大小,通訊雙方各自cache一份header fields表频蛔,既避免了重復(fù)header的傳輸蕾羊,又減小了需要傳輸?shù)拇笮 8咝У膲嚎s算法可以很大的壓縮header帽驯,減少發(fā)送包的數(shù)量從而降低延遲龟再。
這里普及一個(gè)小知識(shí)點(diǎn)。現(xiàn)在大家都知道tcp有slow start的特性尼变,三次握手之后開(kāi)始發(fā)送tcp segment利凑,第一次能發(fā)送的沒(méi)有被ack的segment數(shù)量是由initial tcp window大小決定的。這個(gè)initial tcp window根據(jù)平臺(tái)的實(shí)現(xiàn)會(huì)有差異嫌术,但一般是2個(gè)segment或者是4k的大邪С骸(一個(gè)segment大概是1500個(gè)字節(jié)),也就是說(shuō)當(dāng)你發(fā)送的包大小超過(guò)這個(gè)值的時(shí)候度气,要等前面的包被ack之后才能發(fā)送后續(xù)的包割按,顯然這種情況下延遲更高。intial window也并不是越大越好磷籍,太大會(huì)導(dǎo)致網(wǎng)絡(luò)節(jié)點(diǎn)的阻塞适荣,丟包率就會(huì)增加,具體細(xì)節(jié)可以參考IETF這篇文章**院领。http的header現(xiàn)在膨脹到有可能會(huì)超過(guò)這個(gè)intial window的值了弛矛,所以更顯得壓縮header的重要性。
壓縮算法的選擇SPDY/2使用的是gzip壓縮算法比然,但后來(lái)出現(xiàn)的兩種攻擊方式BREACH**和CRIME**使得即使走ssl的SPDY也可以被破解內(nèi)容丈氓,最后綜合考慮采用的是一種叫HPACK**的壓縮算法。這兩個(gè)漏洞和相關(guān)算法可以點(diǎn)擊鏈接查看更多的細(xì)節(jié)强法,不過(guò)這種漏洞主要存在于瀏覽器端万俗,因?yàn)樾枰ㄟ^(guò)javascript來(lái)注入內(nèi)容并觀(guān)察payload的變化。
重置連接表現(xiàn)更好很多app客戶(hù)端都有取消圖片下載的功能場(chǎng)景饮怯,對(duì)于http1.x來(lái)說(shuō)闰歪,是通過(guò)設(shè)置tcp segment里的reset flag來(lái)通知對(duì)端關(guān)閉連接的。這種方式會(huì)直接斷開(kāi)連接硕淑,下次再發(fā)請(qǐng)求就必須重新建立連接课竣。http2.0引入RST_STREAM類(lèi)型的frame嘉赎,可以在不斷開(kāi)連接的前提下取消某個(gè)request的stream,表現(xiàn)更好于樟。
Server PushServer Push的功能前面已經(jīng)提到過(guò)公条,http2.0能通過(guò)push的方式將客戶(hù)端需要的內(nèi)容預(yù)先推送過(guò)去,所以也叫“cache push”迂曲。另外有一點(diǎn)值得注意的是靶橱,客戶(hù)端如果退出某個(gè)業(yè)務(wù)場(chǎng)景,出于流量或者其它因素需要取消server push路捧,也可以通過(guò)發(fā)送RST_STREAM類(lèi)型的frame來(lái)做到关霸。
流量控制(Flow Control)TCP協(xié)議通過(guò)sliding window的算法來(lái)做流量控制。發(fā)送方有個(gè)sending window杰扫,接收方有receive window队寇。http2.0的flow control是類(lèi)似receive window的做法,數(shù)據(jù)的接收方通過(guò)告知對(duì)方自己的flow window大小表明自己還能接收多少數(shù)據(jù)章姓。只有Data類(lèi)型的frame才有flow control的功能佳遣。對(duì)于flow control,如果接收方在flow window為零的情況下依然更多的frame凡伊,則會(huì)返回block類(lèi)型的frame零渐,這張場(chǎng)景一般表明http2.0的部署出了問(wèn)題。
Nagle Algorithm vs TCP Delayed Acktcp協(xié)議優(yōu)化的一個(gè)經(jīng)典場(chǎng)景是:Nagle算法**和Berkeley的delayed ack算法**的對(duì)立系忙。http2.0并沒(méi)有對(duì)tcp層做任何修改诵盼,所以這種對(duì)立導(dǎo)致的高延遲問(wèn)題依然存在。要么通過(guò)TCP_NODELAY禁用Nagle算法银还,要么通過(guò)TCP_QUICKACK禁用delayed ack算法风宁。貌似http2.0官方建議是設(shè)置TCP_NODELAY。
更安全的SSLHTTP2.0使用了tls的拓展ALPN來(lái)做協(xié)議升級(jí)见剩,除此之外加密這塊還有一個(gè)改動(dòng)杀糯,HTTP2.0對(duì)tls的安全性做了近一步加強(qiáng),通過(guò)黑名單機(jī)制禁用了幾百種不再安全的加密算法苍苞,一些加密算法可能還在被繼續(xù)使用。如果在ssl協(xié)商過(guò)程當(dāng)中狼纬,客戶(hù)端和server的cipher suite沒(méi)有交集羹呵,直接就會(huì)導(dǎo)致協(xié)商失敗,從而請(qǐng)求失敗疗琉。在server端部署http2.0的時(shí)候要特別注意這一點(diǎn)冈欢。
3.2 HTTP2.0里的負(fù)能量SPDY和HTTP2.0之間的曖昧關(guān)系,以及google作為SPDY的創(chuàng)造者盈简,這兩點(diǎn)很容易讓陰謀論者懷疑google是否會(huì)成為協(xié)議的最終收益方凑耻。這其實(shí)是廢話(huà)太示,google當(dāng)然會(huì)受益,任何新協(xié)議使用者都會(huì)從中受益香浩,至于誰(shuí)吃肉类缤,誰(shuí)喝湯看的是自己的本事。從整個(gè)協(xié)議的變遷史也可以粗略看出邻吭,新協(xié)議的誕生完全是針對(duì)業(yè)界現(xiàn)存問(wèn)題對(duì)癥下藥餐弱,并沒(méi)有g(shù)oogle業(yè)務(wù)相關(guān)的痕跡存在,google至始至終只扮演了一個(gè)角色:you can you up囱晴。
HTTP2.0不會(huì)是萬(wàn)金油膏蚓,但抹了也不會(huì)有副作用。HTTP2.0最大的亮點(diǎn)在于多路復(fù)用畸写,而多路復(fù)用的好處只有在http請(qǐng)求量大的場(chǎng)景下才明顯驮瞧,所以有人會(huì)覺(jué)得只適用于瀏覽器瀏覽大型站點(diǎn)的時(shí)候。這么說(shuō)其實(shí)沒(méi)錯(cuò)枯芬,但http2.0的好處不僅僅是multiplexing论笔,請(qǐng)求壓縮,優(yōu)先級(jí)控制破停,server push等等都是亮點(diǎn)翅楼。對(duì)于內(nèi)容型移動(dòng)端app來(lái)說(shuō),比如淘寶app真慢,http請(qǐng)求量大毅臊,多路復(fù)用還是能產(chǎn)生明顯的體驗(yàn)提升。多路復(fù)用對(duì)延遲的改變可以參考下這個(gè)測(cè)試網(wǎng)址**黑界。
HTTP2.0對(duì)于ssl的依賴(lài)使得有些開(kāi)發(fā)者望而生畏管嬉。不少開(kāi)發(fā)者對(duì)ssl還停留在高延遲,CPU性能損耗朗鸠,配置麻煩的印象中蚯撩。其實(shí)ssl于http結(jié)合對(duì)性能的影響已經(jīng)可以?xún)?yōu)化到忽略的程度了,網(wǎng)上也有不少文章可以參考烛占。HTTP2.0也可以不走ssl胎挎,有些場(chǎng)景確實(shí)可能不適合https,比如對(duì)代理服務(wù)器的cache依賴(lài)忆家,對(duì)于內(nèi)容安全性不敏感的get請(qǐng)求可以通過(guò)代理服務(wù)器緩存來(lái)優(yōu)化體驗(yàn)犹菇。
3.3 HTTP2.0的現(xiàn)狀HTTP2.0作為新版本的網(wǎng)絡(luò)協(xié)議肯定需要一段時(shí)間去普及,但HTTP本身屬于應(yīng)用層協(xié)議芽卿,和當(dāng)年的網(wǎng)絡(luò)層協(xié)議IPV6不同揭芍,離底層協(xié)議越遠(yuǎn),對(duì)網(wǎng)絡(luò)基礎(chǔ)硬件設(shè)施的影響就越小卸例。HTTP2.0甚至還特意的考慮了與HTTP1.x的兼容問(wèn)題称杨,只是在HTTP1.x的下面做了一層framing layer肌毅,更使得其普及的阻力變小。所以不出意外姑原,HTTP2.0的普及速度可能會(huì)遠(yuǎn)超大部分人的預(yù)期悬而。
Firefox 2015年在其瀏覽器流量中檢測(cè)到,有13%的http流量已經(jīng)使用了http2.0页衙,27%的https也是http2.0摊滔,而且還處于持續(xù)的增長(zhǎng)當(dāng)中。一般用戶(hù)察覺(jué)不到是否使用了http2.0店乐,不過(guò)可以裝這樣一個(gè)插件**艰躺,安裝之后如果網(wǎng)站是http2.0的,在地址欄的最右邊會(huì)有個(gè)閃電圖標(biāo)眨八。還可以使用這個(gè)網(wǎng)站**來(lái)測(cè)試腺兴。對(duì)于開(kāi)發(fā)者來(lái)說(shuō),可以通過(guò)Web Developer的Network來(lái)查看協(xié)議細(xì)節(jié)廉侧,如下圖:
其中Version:HTTP/2.0已經(jīng)很明確表明協(xié)議類(lèi)型页响,F(xiàn)irefox還在header里面插入了X-Firefox-Spdy:“h2”,也可以看出是否使用http2.0段誊。
Chrome在2015年檢測(cè)到的http2.0流量大概有18%闰蚕。不過(guò)這個(gè)數(shù)字本來(lái)會(huì)更高,因?yàn)镃hrome現(xiàn)在很大一部分流量都在試驗(yàn)QUIC(google正在開(kāi)辟的另一塊疆土)连舍。Chrome上也可以使用類(lèi)似的插件**來(lái)判斷網(wǎng)站是否是使用http2.0没陡。
4. 移動(dòng)端HTTP現(xiàn)狀****4.1 iOS下http現(xiàn)狀iOS系統(tǒng)是從iOS8開(kāi)始才通過(guò)NSURLSession來(lái)支持SPDY的,iOS9+開(kāi)始自動(dòng)支持http2.0索赏。實(shí)際上apple對(duì)http2.0非常有信心盼玄,推廣力度也很大。新版本ATS機(jī)制默認(rèn)使用https來(lái)進(jìn)行網(wǎng)絡(luò)傳輸潜腻。APN(Apple Push Notifiction)在iOS9上也已經(jīng)是通過(guò)http2.0來(lái)實(shí)現(xiàn)的了埃儿。iOS9 sdk里的NSURLSession默認(rèn)使用http2.0,而且對(duì)開(kāi)發(fā)者來(lái)說(shuō)是完全透明的融涣,甚至沒(méi)有api來(lái)知道到底是用的哪個(gè)版本的http協(xié)議童番。
對(duì)于開(kāi)發(fā)者來(lái)說(shuō)到底怎么去配置最佳的http使用方案呢?在我看來(lái)威鹿,因app而異妓盲,主要從兩方面來(lái)考慮:一是app本身http流量是否大而且密集,二是開(kāi)發(fā)團(tuán)隊(duì)本身的技術(shù)條件专普。http2.0的部署相對(duì)容易很多,客戶(hù)端開(kāi)發(fā)者甚至不用做什么改動(dòng)弹沽,只需要使用iOS9的SDK編譯即可檀夹,但缺點(diǎn)是http2.0只能適用于iOS9的設(shè)備筋粗。SPDY的部署相對(duì)麻煩一些,但優(yōu)點(diǎn)是可以兼顧iOS6+的設(shè)備炸渡。iOS端的SPDY可以使用twitter開(kāi)發(fā)的CocoaSPDY方案娜亿,但有一點(diǎn)需要特別處理:
由于蘋(píng)果的TLS實(shí)現(xiàn)不支持NPN,所以通過(guò)NPN協(xié)商使用SPDY就無(wú)法通過(guò)默認(rèn)443端口來(lái)實(shí)現(xiàn)蚌堵。有兩種做法买决,一是客戶(hù)端和server同時(shí)約定好使用另一個(gè)端口號(hào)來(lái)做NPN協(xié)商,二是server這邊通過(guò)request header智能判斷客戶(hù)端是否支持SPDY而越過(guò)NPN協(xié)商過(guò)程吼畏。第一種方法會(huì)簡(jiǎn)單一點(diǎn)督赤,不過(guò)需要從框架層將所有的http請(qǐng)求都map到另一個(gè)port,url mapping可以參考我之前的一篇文章**泻蚊。twitter自己的網(wǎng)站twitter.com使用的是第二種方法躲舌。
瀏覽器端(比如Chrome),server端(比如nginx)都陸續(xù)打算放棄支持spdy了性雄,畢竟google官方都宣布要停止維護(hù)了没卸。spdy會(huì)是一個(gè)過(guò)渡方案,會(huì)隨著iOS9的普及會(huì)逐步消失秒旋,所以這部分的技術(shù)投入需要開(kāi)發(fā)團(tuán)隊(duì)自己去衡量约计。
4.2 Android下http現(xiàn)狀android和iOS情況類(lèi)似,http2.0只能在新系統(tǒng)下支持迁筛,spdy作為過(guò)渡方案仍然有存在的必要煤蚌。
對(duì)于使用webview的app來(lái)說(shuō),需要基于chrome內(nèi)核的webview才能支持spdy和http2.0瑰煎,而android系統(tǒng)的webview是從android4.4(KitKat)才改成基于chrome內(nèi)核的铺然。
對(duì)于使用native api調(diào)用的http請(qǐng)求來(lái)說(shuō),okhttp是同時(shí)支持spdy和http2.0的可行方案酒甸。如果使用ALPN魄健,okhttp要求android系統(tǒng)5.0+(實(shí)際上,android4.4上就有了ALPN的實(shí)現(xiàn)插勤,不過(guò)有bug沽瘦,知道5.0才正式修復(fù)),如果使用NPN农尖,可以從android4.0+開(kāi)始支持析恋,不過(guò)NPN也是屬于將要被淘汰的協(xié)議。
結(jié)束語(yǔ)以上是HTTP從1.x到SPDY盛卡,再到HTTP2.0的一些主要變遷技術(shù)點(diǎn)助隧。HTTP2.0正處于逐步應(yīng)用到線(xiàn)上產(chǎn)品和服務(wù)的階段,可以預(yù)見(jiàn)未來(lái)會(huì)有不少新的坑產(chǎn)生和與之對(duì)應(yīng)的優(yōu)化技巧滑沧,HTTP1.x和SPDY也將在一段時(shí)間內(nèi)繼續(xù)發(fā)揮余熱并村。作為工程師巍实,需要了解這些協(xié)議背后的技術(shù)細(xì)節(jié),才能打造高性能的網(wǎng)絡(luò)框架哩牍,從而提升我們的產(chǎn)品體驗(yàn)棚潦。
參考鏈接:http2 concepts ?· http2 explained**
https://www.chromium.org/spdy/spdy-whitepaper**
作者:victor yu鏈接:https://www.zhihu.com/question/34074946/answer/108588042來(lái)源:知乎著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán)膝昆,非商業(yè)轉(zhuǎn)載請(qǐng)注明出處丸边。