自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

關(guān)于HTTP推送的一些問題

開發(fā) 前端
使用 HTTP 推送,CSS 和 JS 會(huì)在 HTML 請(qǐng)求到達(dá)之后盡快推送出去,發(fā)送它們需要 3 個(gè) RTT(又一次因?yàn)槁龁?dòng)),它們將擁塞窗口增大至 128 KB 左右,將要發(fā)送 HTML 時(shí),一個(gè) RTT 就能可以了。

[[173785]]

上周我在斯達(dá)哥爾摩住了幾天,出席了 HTTP 研討會(huì),參與了不少吸引人的討論。其中一次是關(guān)于 HTTP 推送及其優(yōu)缺點(diǎn)、早期實(shí)驗(yàn)結(jié)果的。

由于早期實(shí)驗(yàn)部署結(jié)果不那么理想,人們對(duì) HTTP 推送大體持著懷疑態(tài)度,不過我想分享下自己更樂觀一些的觀點(diǎn)。

HTTP 推送能做哪些預(yù)加載不能做的事?

從懷疑者那里一再聽到的觀點(diǎn)是,“推送相對(duì)于預(yù)加載來說,只不過節(jié)省了一次 RTT(Round Trip Time)而已”。在實(shí)踐中,這并非總是對(duì)的,有一個(gè)使用案例,推送可以完成,但預(yù)加載無法做到。

利用服務(wù)器思考時(shí)間(think-time)

如今,HTML 響應(yīng)很少只是單純的靜態(tài)資源了。它們通常都是通過數(shù)據(jù)庫獲取所需的信息、使用高級(jí)語言(可能略微慢一些)動(dòng)態(tài)生成的。雖然后端響應(yīng)時(shí)間確實(shí)可以而且應(yīng)當(dāng)優(yōu)化,但幾百毫秒的響應(yīng)時(shí)間也并不常見。

有一個(gè)常見的建議,“提早 flush” HTML,在查詢數(shù)據(jù)庫并構(gòu)建動(dòng)態(tài)內(nèi)容的同時(shí),發(fā)送 HTML 的首個(gè) chunk 塊。但是,并非所有服務(wù)端的構(gòu)架都能這么簡(jiǎn)單地實(shí)現(xiàn)。

另外一個(gè)讓問題變得困難的因素是,需要開始向?yàn)g覽器發(fā)送數(shù)據(jù)時(shí),我們尚無法確定響應(yīng)的構(gòu)建是否會(huì)完全成功。為避免出現(xiàn)響應(yīng)創(chuàng)建邏輯出錯(cuò)(比如說,數(shù)據(jù)庫錯(cuò)誤或者服務(wù)端代碼運(yùn)行失敗),我們需要在應(yīng)用邏輯中創(chuàng)建一種“回滾”已發(fā)送響應(yīng)數(shù)據(jù)的方式,并向用戶展示錯(cuò)誤信息。

盡管這肯定有可能做得到(甚至是自動(dòng)化的),但目前還沒有一種通用的方式能夠作為協(xié)議的一部分。

因此一般場(chǎng)景是,Web 服務(wù)器等待后端數(shù)百毫秒以構(gòu)建頁面,而后開始返回?cái)?shù)據(jù)。這時(shí)候我們就碰到了慢啟動(dòng)(譯者注:slow start,可參考此文),所以首次 RTT 只能發(fā)送大約 14 KB 數(shù)據(jù),第二次 28 KB 左右,如此等等。由此我們知道,將 HTML 發(fā)送出去,需要用去服務(wù)器思考時(shí)間加上慢啟動(dòng)時(shí)間。在思考時(shí)間期間,瀏覽器對(duì)接下來所需的資源一無所知,故也不會(huì)針對(duì)接下來所需資源的關(guān)鍵路徑發(fā)送任何請(qǐng)求。

而且,即使我們?cè)囍P÷斆?,針?duì)那些資源添加 preload 報(bào)頭,若我們不提早 flush 文檔開頭,那還是沒有對(duì)思考時(shí)間加以利用。

現(xiàn)在,將這個(gè)與使用 HTTP 推送能做的事情做個(gè)對(duì)比。服務(wù)器可以利用思考時(shí)間來推送相關(guān)的關(guān)鍵性資源 —— 尤其是 CSS 和 JS。這樣一來,當(dāng)思考時(shí)間結(jié)束時(shí),我們極有可能已將所有關(guān)鍵性資源都推送給瀏覽器了。

還有額外好處,這些資源也預(yù)熱了 TCP 連接,也提升了擁塞窗口(congestion window),確保思考時(shí)間之后的首個(gè) RTT 中,可以使用 28 KB,56 KB,乃至更大的擁塞窗口發(fā)送 HTML(這取決于思考時(shí)間的長(zhǎng)短,以及在此期間我們推送了多少資源)。

一起來看下具體案例:一個(gè) 120 KB 的 HTML 頁面,關(guān)鍵 CSS 有 24KB,關(guān)鍵 JS 有 74 KB,在 100ms RTT、無限帶寬的網(wǎng)絡(luò)環(huán)境下是如何加載的?

沒有 HTTP 推送的情況下,生成 HTML 等待了 300ms,接著 4 次 RTT 發(fā)送 HTML,因?yàn)槁龁?dòng)的緣故,使用了一個(gè) RTT 請(qǐng)求 JS 和 CSS。在首次渲染之前,時(shí)間超過了 800 毫秒。

 無推送情況下的頁面加載

使用 HTTP 推送,CSS 和 JS 會(huì)在 HTML 請(qǐng)求到達(dá)之后盡快推送出去,發(fā)送它們需要 3 個(gè) RTT(又一次因?yàn)槁龁?dòng)),它們將擁塞窗口增大至 128 KB 左右,將要發(fā)送 HTML 時(shí),一個(gè) RTT 就能可以了。首次渲染總時(shí)間: 400 毫秒。

 HTTP 推送情況下的頁面加載

首次渲染加速了 50%!也不算很差嘛。。。

HTTP 推送不盡如意的地方

我認(rèn)為人們?cè)阱e(cuò)誤地使用 HTTP 推送的原因之一是,他們?cè)谀承┎⒉荒芴峁┤魏魏锰幧踔翐p害效率的場(chǎng)景下使用它。

盲目推送靜態(tài)資源

使用 HTTP 推送可能做的錯(cuò)事之一就是告訴你自己,“啊,這些資源是所有頁面都需要的,把它們配置成所有頁面都推送”。

這很糟糕,原因是緩存。在訪問第一個(gè)頁面之后,這些資源很可能就在用戶的瀏覽器緩存中,然而你卻在悶頭推送。你可能會(huì)爭(zhēng)辯說,這可比內(nèi)聯(lián)所有這些資源好多了。是這樣的,不錯(cuò),但,我必須反過來告訴你,內(nèi)聯(lián)資源也是糟糕的主意。

所以,若你在以這種方式盲目推送資源,請(qǐng)確保它是你想要內(nèi)聯(lián)在頁面中的唯一的資源,也就是關(guān)鍵的 CSS。否則,你就是在冒險(xiǎn)讓重復(fù)的請(qǐng)求變慢。

你可能會(huì)以為,流重置(stream resets)會(huì)幫助推送已緩存的資源去避免浪費(fèi)帶寬和時(shí)間。你可能錯(cuò)了。很顯然,并非所有瀏覽器會(huì)檢查緩存并終止已緩存資源的推送。就算它們會(huì)這樣,在流重置信號(hào)到達(dá)服務(wù)器之前,還是使用了一整個(gè) RTT 時(shí)間發(fā)送數(shù)據(jù)。尤其是有多個(gè)資源時(shí),這樣做將可能帶來大量數(shù)據(jù)浪費(fèi)。

將內(nèi)容放入瀏覽器緩存

你可能以為,推送會(huì)將資源放入瀏覽器緩存,可以用來做一些像使當(dāng)前資源失效這樣的工作。至少目前不是如此。研討會(huì)上的討論的話題之一就是現(xiàn)實(shí)問題,可能我們需要改變當(dāng)前的推送行為,支持與瀏覽器緩存直接交互。不過當(dāng)前,推送還做不到這些。推送響應(yīng)進(jìn)入推送緩存,只有真實(shí)請(qǐng)求它們時(shí)才會(huì)放到 HTTP 緩存中。

因此,如果你在推送資源,希望它們?cè)谖磥淼哪硞€(gè)頁面中使用,那么瀏覽器有可能在用到它們之前已經(jīng)將它們?nèi)映鐾扑途彺嬷饬恕?/p>

至少目前的實(shí)現(xiàn)是這樣的。

填補(bǔ) HTML 下發(fā)之后的管道

通常,在頁面的下載循環(huán)中,使用的帶寬之間會(huì)存在間隙。這意味著我們沒能盡快下發(fā)資源,通常這是因?yàn)闉g覽器發(fā)現(xiàn)資源的延遲。

盡管我們應(yīng)當(dāng)盡量下發(fā)頁面所需資源以填滿這些間隙,但通常使用預(yù)加載比推送更好。預(yù)加載將緩存、cookie以及內(nèi)容協(xié)商納入考慮,它不會(huì)像推送那樣存在著過度發(fā)送或錯(cuò)誤發(fā)送的風(fēng)險(xiǎn)。就填補(bǔ)這些間隙而言,推送并無任何優(yōu)勢(shì),所有的只是劣勢(shì)。故最好不要使用推送達(dá)成此目的,使用預(yù)加載吧。

緩存摘要(Cache Digests)

從上面我們可以看到,HTTP 推送的一大缺點(diǎn)就是,服務(wù)器并不必然清楚瀏覽器的緩存狀態(tài),因此在推送時(shí)我們可能會(huì)將已在緩存中存在的資源推送出去。

有一個(gè)標(biāo)準(zhǔn)擴(kuò)展的提案,叫做 Cache Digests。其基本思想是瀏覽器在 HTTP/2 連接初始化之后,向服務(wù)器發(fā)送摘要,服務(wù)器在下發(fā)資源之前能夠精確判斷資源是否已在瀏覽器緩存中存在。

該提案尚處于早期,可能需要簡(jiǎn)化,這樣實(shí)現(xiàn)起來花費(fèi)更少,不過我敢說,離開這個(gè)特性,HTTP 推送只能算半成品。

總結(jié)

HTTP 推送可以用來顯著提升加載性能。正確使用時(shí)能為首個(gè)關(guān)鍵路徑加載提速,帶來性能指標(biāo)的改善。

推送依然是非常新的技術(shù),像其他所有新工具一樣,在找到使用的最優(yōu)方式之前,還有很長(zhǎng)的路要走。這一路多少會(huì)有點(diǎn)痛苦。

是故早期實(shí)驗(yàn)的初始結(jié)果,可能并非全如我們所希望的那樣。讓我們把那些結(jié)果作為標(biāo)志,指示我們關(guān)于推送的使用需要更多聰明才智吧,別妄下結(jié)論說它是無用的特性。

感謝 Tim Kadlec 和 Marcos Caceres 審閱本文(特別感謝 Tim,在制作 RTT 圖解原型時(shí)的幫助)。

責(zé)任編輯:龐桂玉 來源: Linux中國
相關(guān)推薦

2009-06-12 10:25:42

Webservices

2018-06-12 15:39:41

容器部署云平臺(tái)

2021-10-21 06:52:17

Vue3組件 API

2009-11-30 13:51:28

VS2003 Runt

2011-05-31 17:50:07

白盒測(cè)試

2011-11-01 09:29:08

Android 4.0

2018-05-17 14:52:11

Javascripthtmlcss

2011-03-08 14:28:03

proftpdGentoo

2022-01-16 08:04:44

集群部署canal

2018-04-12 09:29:56

HTTP服務(wù)器問題

2009-07-21 10:35:18

margin coll

2009-08-06 16:01:30

C#接口成員

2010-09-17 15:41:46

網(wǎng)絡(luò)協(xié)議分析軟件

2010-05-04 15:59:05

Oracle字符集

2012-12-19 11:40:13

思科路由器

2009-06-10 21:46:02

JavaScript與

2009-06-04 16:28:43

EJB常見問題

2009-06-18 15:14:53

Spring osgi

2009-11-23 13:44:33

PHP5面向?qū)ο?/a>

2011-01-26 16:24:53

Sun甲骨文
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)