編程學(xué)習(xí)網(wǎng) > WEB開發(fā) > 瀏覽器兼容 > Google Chrome中的高性能網(wǎng)絡(luò)
2014
12-03

Google Chrome中的高性能網(wǎng)絡(luò)

  Google Chrome的歷史和指導(dǎo)原則 【譯注】這部分不再詳細(xì)翻譯,只列出核心意思。

  驅(qū)動(dòng)Chrome繼續(xù)前進(jìn)的核心原則包括:

  Speed: 做最快的(fastest)的瀏覽器. Security:為用戶提供最為安全的(most secure)的上網(wǎng)環(huán)境。

  Stability: 提供一個(gè)健壯且穩(wěn)定的(resilient and stable)的Web應(yīng)用平臺。

  Simplicity: 以簡練的用戶體驗(yàn)(simple user experience)封裝精益求精的技術(shù)(sophisticated technology)。

  本文關(guān)將注于第一點(diǎn),速度。

  關(guān)于性能的方方面面 一個(gè)現(xiàn)代瀏覽器就是一個(gè)和操作系統(tǒng)一樣的平臺。在Chrome之前的瀏覽器都是單進(jìn)程的應(yīng)用,所有頁面共享相同的地址空間和資源。引入多進(jìn)程架構(gòu)這是Chrome最為著名的改進(jìn)【譯注:省略一些反復(fù)談?wù)摰募?xì)節(jié)】。

Google Chrome中的高性能網(wǎng)絡(luò)_html_1c3ce373

  一個(gè)進(jìn)程內(nèi),Web應(yīng)用主要需要執(zhí)行三個(gè)任務(wù):獲取資源,頁面 排版及渲染,和運(yùn)行JavaScript。渲染和腳本都是在運(yùn)行中交替以單線程的方式運(yùn)行的,其原因是為了保持DOM的一致性,而JavaScript本 身也是一個(gè)單線程的語言。所以優(yōu)化渲染和腳本運(yùn)行無論對于頁面開發(fā)者還是瀏覽器開發(fā)者都是極為重要的。

  Chrome的渲染引擎是WebKit, JavaScript Engine則使用深入優(yōu)論的V8 (“V8″ JavaScript runtime)。但是,如果網(wǎng)絡(luò)不暢,無論優(yōu)化V8的JavaScript執(zhí)行,還是優(yōu)化WebKit的解析和渲染,作用其實(shí)很有限。巧婦難為無米之炊,數(shù)據(jù)沒來就得等著!

  相對于用戶體驗(yàn),作用最為明顯的就是如何優(yōu)化網(wǎng)絡(luò)資源的加載順 序、優(yōu)先級及每一個(gè)資源的延遲時(shí)間(latency)。也許你察覺不到,Chrome網(wǎng)絡(luò)模塊每天都在進(jìn)步,逐步降低每個(gè)資源的加載成本:向DNS lookups學(xué)習(xí),記住頁面拓?fù)浣Y(jié)構(gòu)(topology of the web), 預(yù)先連接可能的目標(biāo)網(wǎng)址,等等,還有很多。從外面來看就是一個(gè)簡單的資源加載的機(jī)制,但在內(nèi)部卻是一個(gè)精彩的世界。

  關(guān)于Web應(yīng)用 開始正題前,還是先來了解一下現(xiàn)在網(wǎng)頁或者Web應(yīng)用在網(wǎng)絡(luò)上的需求。

  HTTP Archive 項(xiàng)目一直在追蹤網(wǎng)頁構(gòu)建。除了頁面內(nèi)容外,它還會分析流行頁面使用的資源數(shù)量,類型,頭信息以及不同目標(biāo)地址的元數(shù)據(jù)(metadata)。下面是2013年1月的統(tǒng)計(jì)資料,由300,000目標(biāo)頁面得出的平均數(shù)據(jù):

Google Chrome中的高性能網(wǎng)絡(luò)_html_m52ecc48a

  1280 KB 包含88個(gè)資源(Images,JavaScript,CSS …)

  連接15個(gè)以上的不同主機(jī)(distinct hosts)。

  這些數(shù)字在過去幾年中一直持續(xù)增長( steadily increasing ),沒有停下的跡象。這說明我們正不斷地建構(gòu)一個(gè)更加龐大的、野心勃勃的網(wǎng)絡(luò)應(yīng)用。還要注意,平均來看每個(gè)資源不過12KB, 表明絕大多數(shù)的網(wǎng)絡(luò)傳輸都是短促(short and bursty)的。這和TCP針對大數(shù)據(jù)、流式(streaming)下載的方向不一致,正因?yàn)槿绱耍肓艘恍┎l(fā)癥。下面就用一個(gè)例子來抽絲剝繭,一窺究竟……

  一個(gè)Resource Request的一生 W3C的Navigation Timing specification定義了一組API,可以觀察到瀏覽器的每一個(gè)請求(request)的時(shí)序和性能數(shù)據(jù)。下面了解一些細(xì)節(jié):

Google Chrome中的高性能網(wǎng)絡(luò)_html_m69436d46

  給定一個(gè)網(wǎng)頁資源地址后,瀏覽器就會檢查本地緩存和應(yīng)用緩存。如果之前獲取過并且有相應(yīng)的緩存信息(appropriate cache headers)(如Expires, Cache-Control, etc.), 就會用緩存數(shù)據(jù)填充這個(gè)請求,畢竟最快的請求就是沒有請求(the fastest request is a request not made)。否則,我們重新驗(yàn)證資源,如果已經(jīng)失效(expired),或者根本就沒見過,一個(gè)耗費(fèi)網(wǎng)絡(luò)的請求就無法避免地發(fā)送了。

  給定了一個(gè)主機(jī)名和資源路徑后,Chrome先是檢查現(xiàn)有已建立的連接(existing open connections)是否可以復(fù)用, 即sockets指定了以(scheme、host和port)定義的連接池(pool)。但如果配置了一個(gè)代理,或者指定了 proxy auto-config (PAC)腳本,Chrome就會檢查與proxy的連接。PAC腳本基于URL提供不同的代理,或者為此指定了特定 的規(guī)則。與每一個(gè)代理間都可以有自己的socket pool。最后,上述情況都不存在,這個(gè)請求就會從DNS查詢(DNS lookup)開始了,以便獲得它的IP地址。

  幸運(yùn)的話,這個(gè)主機(jī)名已經(jīng)被緩存過。否則,必須先發(fā)起一個(gè) DNS Query。這個(gè)過程所需的時(shí)間和ISP,頁面的知名度,主機(jī)名在中間緩存(intermediate caches)的可能性,以及authoritative servers的響應(yīng)時(shí)間這些因素有關(guān)。也就是說這里變量很多,不過一般還不致于到幾百毫秒那么夸張。

Google Chrome中的高性能網(wǎng)絡(luò)_html_15238f79

  拿到解析出的IP后,Chrome就會在目標(biāo)地址間打開一個(gè)新TCP連接,我們就要執(zhí)行一個(gè)3度握手(“three-way handshake”): SYN > SYN-ACK > ACK。這個(gè)操作每個(gè)新的TCP連接都必須完成,沒有捷徑。根據(jù)遠(yuǎn)近,路由路徑的選擇,這個(gè)過程可能要耗時(shí)幾百毫秒,甚至幾秒。而到現(xiàn)在,我們連一個(gè)有效的字節(jié)都還沒收到。

  當(dāng)TCP握手完成了,如果我們連接的是一個(gè)HTTPS地址,還有一個(gè)SSL握手過程,同時(shí)又要增加最多兩輪的延遲等待。如果SSL會話被緩存了,就只需一次。

  最后,Chrome終于要發(fā)送HTTP請求了 (如上面圖示中的requestStart)。 服務(wù)器收到請求后,就會傳送響應(yīng)數(shù)據(jù)(response data)回到客戶端。這里包含最少的往返延遲和服務(wù)的處理時(shí)間。然后一個(gè)請求就完成了。但是,如果是一個(gè)HTTP重定向(redirect)的話?我們 又要從頭開始這個(gè)過程。如果你的頁面里有些冗余的重定向,最好三思一下!

  你得出所有的延遲時(shí)間了嗎? 我們假設(shè)一個(gè)典型的寬帶環(huán)境:沒有本地緩存,相對較快的DNS lookup(50ms), TCP握手,SSL協(xié)商,以及一個(gè)較快服務(wù)器響應(yīng)時(shí)間(100ms)和一次延遲(80ms,在美國國內(nèi)的平均值): 50ms for DNS 80ms for TCP handshake (one RTT)

  160ms for SSL handshake (two RTT’s)

  40ms (發(fā)送請求到服務(wù)器)

  100ms (服務(wù)器處理)

  40ms (服務(wù)器回傳響應(yīng)數(shù)據(jù))

  一個(gè)請求花了470毫秒, 其中80%的時(shí)間被網(wǎng)絡(luò)延遲占去了??吹搅税?,我們真得有很多事情要做!事實(shí)上,470毫秒已經(jīng)很樂觀了:

  如果服務(wù)器沒有達(dá)到到初始TCP的擁塞窗口(congestion window),即4-15KB,就會引入更多的往返延遲。 SSL延遲也可能變得更糟。如果需要獲取一個(gè)沒有的認(rèn)證(certificate)或者執(zhí)行 online certificate status check (OCSP), 都會讓我們需要一個(gè)新的TCP連接,又增加了數(shù)百至上千毫秒的延遲。

  怎樣才算”夠快”? 前面可以看到服務(wù)器響應(yīng)時(shí)間僅是總延遲時(shí)間的20%,其它都被DNS,握手等操作占用了。過去用戶體驗(yàn)研究( user experience research )表明用戶對延遲時(shí)間的不同反應(yīng):

  延遲及用戶反應(yīng) 0 – 100ms 迅速 100 – 300ms 有點(diǎn)慢 300 – 1000ms 機(jī)器還在運(yùn)行 1s+ 想想別的事…… 10s+ 我一會再來看看吧…

  上表同樣適用于頁面的性能表現(xiàn): 渲染頁面,至少要在250ms內(nèi)給個(gè)回應(yīng)來吸引住用戶。這就是簡單地針對速度。從Google, Amazon, Microsoft,以及其它數(shù)千個(gè)站點(diǎn)來看,額外的延遲直接影響頁面表現(xiàn):流暢的頁面會吸引更多的瀏覽、以及更強(qiáng)的用戶吸引力(engagement) 和頁面轉(zhuǎn)換率(conversion rates).

  現(xiàn)在我們知道了理想的延遲時(shí)間是250ms,而前面的示例告訴我們,DNS Lookup, TCP和SSL握手,以及request的準(zhǔn)備時(shí)間花去了370ms, 即便不考慮服務(wù)器處理時(shí)間,我們也超出了50%。

  對于絕大多數(shù)的用戶和網(wǎng)頁開發(fā)者來說,DNS, TCP,以及SSL延遲都是透明,很少有人會想到它。這也就是為什么Chrome的網(wǎng)絡(luò)模塊那么的復(fù)雜。

  我們已經(jīng)識別出了問題,下面讓我們深入一下實(shí)現(xiàn)的細(xì)節(jié)…

掃碼二維碼 獲取免費(fèi)視頻學(xué)習(xí)資料

Python編程學(xué)習(xí)

查 看2022高級編程視頻教程免費(fèi)獲取