使用 HTTP/2 提升性能的 7 個(gè)建議
歷史悠久的超文本傳輸協(xié)議,即HTTP標(biāo)準(zhǔn),最近版本升級(jí)了。HTTP/2在2015年5月被批準(zhǔn),目前已經(jīng)在很多Web瀏覽器和服務(wù)器中得到實(shí)現(xiàn)(包括NGINX Plus和開源NGINX)。大約有三分之二的瀏覽器已經(jīng)支持HTTP/2,而且這個(gè)比例每月都在增加。
HTTP/2構(gòu)建在Google SPDY協(xié)議基礎(chǔ)之上,Chrome將在2016年年初停止對(duì)后者的支持。NGINX是最早支持SPDY的,如今同樣率先支持了HTTP/2。為此,我們還發(fā)布了詳盡的白皮書(PDF),介紹了HTTP/2以及它如何基于SPDY構(gòu)建,并展示了如何實(shí)現(xiàn)這個(gè)新協(xié)議。
HTTP/2的重要特性完全源自SPDY。
-
HTTP/2是二進(jìn)制(而文本)協(xié)議,因此更簡(jiǎn)潔高效;
-
它針對(duì)每個(gè)域只使用一個(gè)多路復(fù)用的連接,而不是每個(gè)文件一個(gè)連接;
-
首部使用特制的HPACK協(xié)議(而非SPDY中使用的gzip)壓縮;
-
HTTP/2設(shè)計(jì)了復(fù)雜的優(yōu)先級(jí)排定規(guī)則,幫助瀏覽器首先請(qǐng)求最急需的文件,而NGINX已經(jīng)支持(SPDY的方案要簡(jiǎn)單一些)。
現(xiàn)在,你需要決定是否遷移到HTTP/2,而其中關(guān)鍵是知道如何***限度地利用它。這篇文章會(huì)帶你了解從性能角度考慮為什么要做這個(gè)決定,以及如何實(shí)現(xiàn)。接下來(lái)我們要逐一討論關(guān)于HTTP/2性能的7個(gè)小建議。
-
現(xiàn)在是否需要遷移到HTTP/2
-
終止HTTP/2和TLS
-
考慮從SPDY開始
-
找出為HTTP/1.x優(yōu)化的代碼
-
部署HTTP/2或SPDY
-
再談HTTP/1.x優(yōu)化
-
實(shí)現(xiàn)智能分域
注意:嚴(yán)格來(lái)講,SPDY和HTTP/2都不需要TLS,但它們?cè)谑褂肧SL/TLS的時(shí)候用處***,而且瀏覽器只在使用SSL/TLS時(shí)才支持SPDY或HTTP/2。
建議一:現(xiàn)在是否需要遷移到HTTP/2
實(shí)現(xiàn)HTTP/2很簡(jiǎn)單,看看我們的白皮書就明白了。不過(guò),HTTP/2并不是***的銀彈,它只對(duì)某些Web應(yīng)用有用,對(duì)另外一些則沒(méi)那么有用。
如果你使用SSL/TLS(以后簡(jiǎn)稱TLS),那么HTTP/2可以提升網(wǎng)站性能。如果你沒(méi)有,那在使用HTTP/2之前要先支持TLS。這時(shí)候,使用TLS的性能損耗大致可以被使用HTTP/2的性能提升抵銷。不過(guò)還是建議你在實(shí)際應(yīng)用之前先測(cè)試一下。
HTTP/2有五大優(yōu)勢(shì)。
-
每個(gè)服務(wù)器只用一個(gè)連接。HTTP/2對(duì)每個(gè)服務(wù)器只使用一個(gè)連接,而不是每個(gè)文件一個(gè)連接。這樣,就省掉了多次建立連接的時(shí)間,這個(gè)時(shí)間對(duì)TLS尤其明顯,因?yàn)門LS連接費(fèi)時(shí)間。
-
加速TLS交付。HTTP/2只需一次耗時(shí)的TLS握手,并且通過(guò)一個(gè)連接上的多路利用實(shí)現(xiàn)***性能。HTTP/2還會(huì)壓縮首部數(shù)據(jù),省掉HTTP/1.x時(shí)代所需的一些優(yōu)化工作,比如拼接文件,從而提高緩存利用率。
-
簡(jiǎn)化Web應(yīng)用。使用HTTP/2可以讓W(xué)eb開發(fā)者省很多事,因?yàn)椴挥迷僮瞿切┽槍?duì)HTTP/1.x的優(yōu)化工作了。
-
適合內(nèi)容混雜的頁(yè)面。HTTP/2特別適合混合了HTML、CSS、JavaScript、圖片和有限多媒體的傳統(tǒng)頁(yè)面。瀏覽器可以優(yōu)先安排那些重要的文件請(qǐng)求,讓頁(yè)面的關(guān)鍵部分先出現(xiàn),快出現(xiàn)。
-
更安全。通過(guò)減少TLS的性能損失,可以讓更多應(yīng)用使用TLS,從而讓用戶信息更安全。
相應(yīng)地,HTTP/2也有五個(gè)不足之處。
-
單連接開銷比較大。HPACK數(shù)據(jù)壓縮算法會(huì)更新兩端的查找表。這樣可以讓連接有狀態(tài),而破壞狀態(tài)就意味著要重建查找表,另外單連接占用內(nèi)存較多。
-
你可能不需要SSL。如果你的數(shù)據(jù)不需要保護(hù),或者已經(jīng)使用DRM或其他編碼進(jìn)行保護(hù)了,那么TLS的安全性對(duì)你可能無(wú)所謂。
-
需要拋棄針對(duì)HTTP/1.x的優(yōu)化。HTTP/1.x優(yōu)化在支持HTTP/2的瀏覽器中會(huì)影響性能,因此可能需要花時(shí)間把它們推倒重來(lái)。
-
對(duì)下載大文件不利。如果你的應(yīng)用主要提供大文件下載或者流媒體播放,那可能不想用TLS,而且在只有一個(gè)流的情況下,多路復(fù)用也體現(xiàn)不出什么優(yōu)勢(shì)。
-
你的客戶也許不在乎。你的客戶很可能不在乎他分享的自家貓咪的視頻是否受到TLS和HTTP/2的保護(hù)。
總之,一切要看性能。這方面,有好消息也有壞消息。
好消息是我們?cè)趦?nèi)部對(duì)NGINX做過(guò)測(cè)試,結(jié)果從理論上能夠得到印證:對(duì)于要通過(guò)典型網(wǎng)絡(luò)延遲請(qǐng)求的混合內(nèi)容網(wǎng)頁(yè),HTTP/2的性能好于HTTP/1.x和HTTPS?;谶B接的RTT,結(jié)果可以分三種情況。
-
很低的RTT(0-20ms):HTTP/1.x、HTTP/2和HTTPS基本無(wú)差別。
-
典型網(wǎng)絡(luò)RTT(30-250ms):HTTP/2比HTTP/1.x快,而且它們都比HTTPS快。美國(guó)兩個(gè)相鄰城市間的RTT約為30 ms,而東西海岸間(約3000英里)則約為70 ms。東京到倫敦間最短路徑的RTT大約240 ms。
-
高RTT(300ms及以上):HTTP/1.x比HTTP/2快,后者又比HTTPS快。
這張圖顯示了***渲染的時(shí)間,也就是用戶***次在自己屏幕上看到網(wǎng)頁(yè)內(nèi)容的時(shí)間。這個(gè)時(shí)間一般認(rèn)為關(guān)系到用戶對(duì)網(wǎng)站響應(yīng)速度的感知。
要想了解我們測(cè)試的更多內(nèi)容,請(qǐng)看這個(gè)HTTP/2的介紹視頻,來(lái)源是nginx.conf 2015。
然而,每個(gè)網(wǎng)頁(yè)都不相同,實(shí)際上每個(gè)用戶的會(huì)話也不一樣。如果你托管流媒體或提供大文件下載,那你的決定可能不一樣,甚至相反。
你最終可能發(fā)現(xiàn)投入產(chǎn)出比并不明顯。如果是這樣,那你得多學(xué)習(xí)一下,針對(duì)自己的內(nèi)容多做一些測(cè)試,然后咱們可以聊一聊。(想找點(diǎn)資料?可以看看NGINX網(wǎng)絡(luò)研討:What’s New in HTTP/2?)。
建議二:終止HTTP/2和TLS
終止協(xié)議意味著客戶端使用期望的協(xié)議連接代理服務(wù)器,比如TLS或HTTP/2,然后代理服務(wù)器再去連接應(yīng)用服務(wù)器、數(shù)據(jù)庫(kù)服務(wù)器等,但不需要使用相同的協(xié)議,如下圖所示。
使用獨(dú)立的服務(wù)器終止協(xié)議意味著使用多服務(wù)器架構(gòu)。多服務(wù)器可能是多個(gè)物理服務(wù)器、多個(gè)虛擬服務(wù)器,或者AWS這樣的云環(huán)境中的多個(gè)虛擬服務(wù)器實(shí)例。多服務(wù)器就比單服務(wù)器復(fù)雜,或者比應(yīng)用服務(wù)器/數(shù)據(jù)庫(kù)服務(wù)器的組合復(fù)雜。不過(guò),多服務(wù)器架構(gòu)有很多好處,而且很多流量大的網(wǎng)站也必須用這種架構(gòu)。
配置了服務(wù)器或者虛擬服務(wù)器之后,很多事情都成為可能。新服務(wù)器可以分擔(dān)其他服務(wù)器的負(fù)載,可用于負(fù)載平衡、靜態(tài)文件緩存和其他用途。另外,也可以讓添加和替換應(yīng)用服務(wù)器或其他服務(wù)器更容易。
NGINX和NGINX Plus經(jīng)常被用來(lái)終止TLS和HTTP/2協(xié)議、負(fù)載平衡。已有環(huán)境不必改動(dòng),除非要把NGINX服務(wù)器挪到前端。
建議三:考慮從SPDY開始
SPDY是HTTP/2的上一代,總體性能相同。因?yàn)樗呀?jīng)出現(xiàn)好幾年了,所以有很多瀏覽器支持SPDY卻不支持HTTP/2。不過(guò),在本文寫作時(shí),這個(gè)支持上的差距正在縮小。具體來(lái)說(shuō),有三分之二的瀏覽器支持HTTP/2,而有五分之四的瀏覽器支持SPDY。
如果你著急采用新的Web傳輸協(xié)議,又想盡可能覆蓋更多用戶,可以先從SPDY開始。然后到2016年初,即谷歌不再支持SPDY的時(shí)候,再切換到 HTTP/2,很簡(jiǎn)單,至少在NGINX中如此。那時(shí)候,更多用戶會(huì)擁有支持HTTP/2的瀏覽器,而你已經(jīng)為其中大部分用戶提供了很好的性能。
建議四:找出為HTTP/1.x優(yōu)化的代碼
在決定采用HTTP/2之前,首先得知道你的代碼有哪些是針對(duì)HTTP/1.x優(yōu)化過(guò)的。大概有四方面的優(yōu)化。
-
分域存儲(chǔ)。為了實(shí)現(xiàn)并行請(qǐng)求文件,你可能把文件分散到了不同的域里,CDN會(huì)自動(dòng)這么做。但分域存儲(chǔ)會(huì)影響HTTP/2的性能,建議使用HTTP/2友好的分域存儲(chǔ)(參見建議七),只針對(duì)HTTP/1.x用戶分域。
-
圖片精靈(sprites)。圖片精靈把很多圖片拼成一個(gè)文件,然后通過(guò)代碼按需取得每個(gè)圖片。圖片精靈在HTTP/2的環(huán)境下沒(méi)太大用處,但還是有點(diǎn)用的。
-
拼接的代碼文件。與使用圖片精靈的原因類似,很多獨(dú)立的文件也會(huì)被弄成一個(gè),然后瀏覽器再?gòu)钠渲姓业讲⑦\(yùn)行需要的文件。
-
內(nèi)聯(lián)文件。CSS代碼、JavaScript代碼,甚至圖片等被直接插到HTML文件中的內(nèi)容。這樣可以減少文件傳輸,代價(jià)是初始HTML文件較大。
后面三種優(yōu)化都涉及把小文件塞進(jìn)一個(gè)較大的文件里,目的是減少新建連接的初始化和握手,這些操作對(duì)TLS而言非常費(fèi)時(shí)間。
***種優(yōu)化即分域存儲(chǔ)恰恰相反,強(qiáng)制打開多個(gè)連接,目的是并行地從不同的域獲取文件。這兩種看似矛盾的技術(shù)對(duì)于HTTP/1.x下的站點(diǎn)卻十分有效。然而,要用好這兩種技術(shù),必須投入大量時(shí)間、精力和資源,用于實(shí)現(xiàn)、管理和運(yùn)維。
在采用HTTP/2之前,需要找出應(yīng)用了這些優(yōu)化的代碼,分析一下它們會(huì)不會(huì)影響你的應(yīng)用設(shè)計(jì)和工作流程。這樣在遷移到HTTP/2之后,就可以著手改造它們,甚至撤銷某些優(yōu)化。
建議五:部署HTTP/2或SPDY
事實(shí)上,部署HTTP/2或SPDY并不難。如果你使用NGINX,只要在配置文件中啟動(dòng)相應(yīng)的協(xié)議就可以了,參見這里了解如何啟用HTTP/2。瀏覽器和服務(wù)器會(huì)協(xié)商采用什么協(xié)議,如果瀏覽器支持HTTP/2(而且也在使用TLS),就會(huì)使用HTTP/2。
配置完服務(wù)器后,使用支持HTTP/2瀏覽器的用戶就會(huì)基于HTTP/2運(yùn)行你的應(yīng)用,而使用舊版本瀏覽器的用戶則會(huì)繼續(xù)使用HTTP/1.x運(yùn)行你的應(yīng)用,如下圖所示。如果你的網(wǎng)站流量非常大,那么應(yīng)該監(jiān)測(cè)改變前后的性能,對(duì)于性能降低的情況,可能就得撤銷更改。
注意:使用HTTP/2及其單連接之后,NGINX某些配置的重要性會(huì)很明顯,特別要注意的是output_buffers、proxy_buffers和ssl_buffer_size等指令,多測(cè)試一下。參見常規(guī)配置提示,特定的SSL建議(在這里 和 這里),以及NGINX關(guān)于SSL性能的白皮書。
注意:使用HTTP/2傳輸密文要格外注意。HTTP/2的RFC中有一個(gè)長(zhǎng)長(zhǎng)的列表,列出了要避免的加密套件。建議你自己也搞一個(gè)表格,啟用ssl_buffer_size,然后在所有常用的瀏覽器版本下測(cè)試你想用的加密套件。
建議六:再談HTTP/1.x優(yōu)化
你說(shuō)奇怪不,撤銷和修改針對(duì)HTTP/1.x優(yōu)化的代碼居然是實(shí)現(xiàn)HTTP/2最有創(chuàng)意的部分。這里面有幾個(gè)問(wèn)題要注意,因?yàn)楹芏嗍略趺醋龆际强梢缘摹?/p>
在開始運(yùn)作之前,必須考慮舊版本瀏覽器用戶是否好過(guò)。之后,可以采取三個(gè)策略撤銷和修改HTTP/1.x的優(yōu)化。
-
什么也不用做。假如你并沒(méi)有針對(duì)HTTP/1.x做過(guò)優(yōu)化,或者只做過(guò)少量?jī)?yōu)化,那么你幾乎什么也不用做,就可以直接遷移到HTTP/2。
-
有選擇地去做。第二種情況是減少合并某些文件,而不是完全不合并。比如,牽扯到很多場(chǎng)景的圖片精靈就不用動(dòng),而被塞得滿滿的HTML可能就要分離出來(lái)一些。
-
完全撤銷HTTP/1.x優(yōu)化(不過(guò)請(qǐng)先參考建議七中關(guān)于分域存儲(chǔ)的建議)??梢圆辉僮鲆郧白鲞^(guò)的任何優(yōu)化。
緩存還是普適的。理論上,緩存操作非常適合小文件特別多的情況。但是,小文件多也意味著文件I/O多。因此一些相近文件的合并還是必要的,一方面要考慮工作流程,另一方面要考慮應(yīng)用性能。建議多關(guān)注一下其他人在過(guò)渡到HTTP/2過(guò)程中的一些經(jīng)驗(yàn)。
建議七:實(shí)現(xiàn)智能分域
分域存儲(chǔ)可能是最極端但也最成功的HTTP/1.x優(yōu)化策略。它能夠提升HTTP/1.x下的應(yīng)用性能,但在HTTP/2之下,其性能提升可以忽略不講(因?yàn)橹挥幸粋€(gè)連接。)
對(duì)HTTP/2友好的分域,要保證以下兩點(diǎn)。
-
讓多個(gè)域名解析到同一個(gè)IP。
-
確保證書包含通配符,以便所有分域名都可以使用,適當(dāng)?shù)亩嘤蜃C書當(dāng)然也可以。
具體細(xì)節(jié),請(qǐng)參考這里。
有了這些保障,分域還會(huì)繼續(xù)對(duì)HTTP/1.x有效,即域名仍然可以觸發(fā)瀏覽器創(chuàng)建更多連接,但對(duì)HTTP/2則無(wú)效,因?yàn)檫@些域名會(huì)被看成同一個(gè)域,一個(gè)連接就可以訪問(wèn)所有域名了。
小結(jié)
HTTP/2和TLS組合可以提升你的站點(diǎn)性能,并且讓用戶覺得你的網(wǎng)站很安全。無(wú)論你是率先在自己的應(yīng)用里實(shí)現(xiàn)HTTP/2,還是要趕超競(jìng)爭(zhēng)對(duì)手,都可以又快又好地實(shí)現(xiàn)對(duì)HTTP/2的支持。
希望這篇文章能讓你以最少的努力獲得***的HTTP/2性能收益,而且從此你可以把注意力集中到編寫更快、更有效、更安全的應(yīng)用上,讓自己的應(yīng)用更容易維護(hù)和運(yùn)維。
參考資源
-
要全面了解HTTP/2,可以看看NGINX的白皮書(PDF)。
-
在Can I use網(wǎng)站中可以查到瀏覽器對(duì)各種前端技術(shù)的支持情況,包括SPDY和HTTP/2。
-
要了解我們測(cè)試的細(xì)節(jié),參考這里HTTP/2 presentation。
-
NGINX有一個(gè)Web研討班:What’s New in HTTP/2?,討論了核心特性并給出了實(shí)現(xiàn)建議。
-
要了解NGINX關(guān)于性能的建議,請(qǐng)參考我們的博客:10 Tips for 10x Application Performance。