從輸入 URL 到頁面加載完的過程中都發生了什麼事情 —— 網絡優化篇

http://oilbeater.com/技術相關/2014/05/09/from-url-to-webpage.html  -- 原博文,表示感謝!

話說這些年來我最喜歡問的面試題是『從輸入 URL 到頁面加載完的過程中都發生了什麼事情?』,個人覺得這道題非常非常難,既考深度又考廣度,至今還沒有人的回答讓我滿意,所以我想自己挑戰一下,整理出一篇文章,有哪位大牛也想來一起挑戰麼? @JS小組 @前端交流

想到這不就是我這兩年來研究的東西麼,於是就接受一下挑戰。網上已經有很多版本的答案了比如這裏這裏。這道題可以從瀏覽器端,網絡傳輸和服務器端詳細展開,每一部分都可以說上好幾天,每個人都能說上幾句又不可能說全,所以說的方向和角度就很重要了。其中客戶端和服務器端的工作已經有太多的人說了,本文來講一下中間部分的網絡傳輸。可是網絡傳輸部分相對來說是比較簡單的,有成文的規範和協議基本和背課文一樣,本文就講點帶花的,講一下現有針對網絡的優化部分,以防止和別人雷同。

一個HTTP請求的過程

爲了簡化我們先從一個HTTP請求開始,簡要介紹一下一個HTTP求情的網絡傳輸過程,也就是所謂的“從輸入 URL 到頁面下載完的過程中都發生了什麼事情”

  1. DNS Lookup 先獲得URL對應的IP地址

  2. Socket Connect 瀏覽器和服務器建立TCP連接

  3. Send Request 發送HTTP請求

  4. Content Download 服務器發送響應

如果下到物理層去講就有點耍流氓了,如果這些你還認可這幾個步驟的話,我們就來講一下這裏面存在的性能問題。

  1. 如果你對DNS的查詢還有印象的話現在反思一下,DNS Lookup就是爲了獲取一串IP地址要和無數個DNS服務器進行通信,這要消耗多少時間?別忘了你查詢完了的時候你還沒和那邊的服務器通信呢。

  2. TCP連接要三次握手,如果服務器很遠的話這三次握手要花多少時間?別忘了建立連接之後你還沒發請求呢。(通常到這裏0.5秒就出去了)

  3. 發送HTTP請求的時候你要知道一點就是我們的網絡帶寬上行和下行通常是不一樣的,通常上行的帶寬會小一些,一個的話還好,但是現在的網頁通常都會後續請求很多資源,帶寬小的時候上行擁塞怎麼辦?別忘了已經到第三步了,服務器還沒給你發響應呢,現在你的瀏覽器還什麼都畫不出來。

  4. 終於到了服務器發響應了,不巧你訪問的這個服務器比較忙,好幾萬個人都要這個資源,服務器的上行帶寬也是有限的,怎麼辦?

我覺得我出了幾道還不錯的面試題。順便提一下,前兩步的延遲和網絡帶寬的影響不大;後兩步加帶寬是能一定程度緩解,不過你要有錢,而且很貴。雖說博主做過Webkit本地渲染的優化,但是深知網頁加載的主要時間還是浪費在網絡通信上,所以在這些步驟上的優化會比你在瀏覽器內核的優化省力且效果明顯。

網絡方面的主要優化手段,博主總結一下不外乎緩存,預取,壓縮,並行。以後如果再有面試問性能優化之類的問題,大家都可以照着這個思路去考慮,下面就分階段介紹一下現有的優化手段。

DNS 優化

對於DNS優化,緩存無疑是最簡單粗暴且效果明顯的了。說到緩存就一定要提到緩存層級:

  1. 瀏覽器DNS緩存,chrome可以看 chrome://net-internals/#dns

  2. 系統DNS緩存

  3. hosts文件,牆裏的小夥伴們應該有印象

  4. 各個DNS服務器上的緩存

當然DNS緩存失效期通常都比較短,很多情況下都要再去查找,爲了降低用戶體驗到的延遲(注意這裏不是網絡延時)預取是一個不錯的方法。比如說你敲網址的時候還沒有敲完,但是瀏覽器根據你的歷史發現你很有可能去訪問哪個網站就提前給你做dns預取了,比如你打了一個“w”的時候,chrome已經幫你去找weibo.com的ip地址了。chrome用戶可以看一下 chrome://predictors/ 你就知道了。

此外瀏覽器還會記錄你過去的歷史知道每個域名下通常還會有哪些其他的鏈接建立起網站的拓撲結構,當你訪問這個域名下的網站他就會預先對其他鏈接的域名進行DNS解析可以參照 chrome://dns/。

TCP 優化

看到前面的DNS的具體優化這麼繁雜,知道這簡單的一步沒那麼簡單了吧。結果到TCP這一步優化反而簡單了,因爲剛纔dns已經把ip都預先弄到了那麼我們順着剛纔的步驟再建立連接就好了。所以在你敲第一個字母的時候dns解析完了就去建立連接了,這時候你可能網址還沒敲完。當你剛訪問一個網站的時候瀏覽器刷刷刷的幫你把到別的服務器的TCP連接給你建好。

HTTP傳輸優化

寫到這裏可能有人會想,既然已經把TCP連接建立好了,那我乾脆預取更進一步,把所有的鏈接內容直接預取下來不就好了,這樣我網址還沒敲完網頁就已經加載完成了。這個想法是好的,但現實卻是殘酷的。因爲要記住我們的帶寬是有限的,DNS和TCP連接量級都比較輕,對網絡帶寬不會佔據太多,但是HTTP傳輸就不一樣瞭如果你所有鏈接都去預取的話你的帶寬很快就被佔滿了,這樣你正常的請求無法得到滿足,性能反而會嚴重下降。

緩存就又出現了,提緩存必提層次結構。

  1. PageCache 這個是最快的了,直接在內存中緩存了現有網頁的dom結構和渲染結果,這就是你爲什麼在點前進後退的時候會這麼快。

  2. HTTP Cache 文件級別的Cache存在本地的文件系統上按照RFC2616實現。

  3. 代理Cache 如果是通過代理服務器上網的話,代理服務器通常也會按照緩存標準

  4. CDN 一個地理上離你很近的內容服務器,比如說你在北京請求杭州淘寶的一個圖片,結果在北京的一個CDN上有這個圖片,那麼就不用去杭州了。

  5. DMOC(distributed memory object caching system)CDN主要存放的是靜態數據,但是網頁中通常有很多動態的數據需要查數據庫,流量多了壓力就會很大,通常服務器外圍還會有一層內存緩存服務器,專門緩存這些數據庫中的對象,據《淘寶技術這10年》稱可以減少99.5%的數據庫訪問。

  6. Server 其實真正落在服務器上的請求已經不多了。

大家看到這裏有沒有想到能在什麼地方再加一層緩存呢?其實可以在2和3之間加,也就是在路由器上加緩存。小米的路由器和搜狗合作的預取引擎其實就相當於是在路由器上加一層緩存款順便智能預取一下。博主爲什麼在這裏另起一段專門談小米呢,難不成是小米的水軍?纔不是呢,是因爲博主看到這個消息的時候心都涼了,和博主的畢設撞車了有木有。去年在360剛出隨身WiFi的時候博主想到了這麼個點子,還想着把這個東西做出來之後用這個創業和360談合作。結果最近剛做完,論文也投出去了,幻想着開啓人生巔峯,顛覆行業結果就發現小米和搜狗出了這麼個一樣的東西還都商業化了。說好的人生巔峯就這樣沒有了,早知道去年就先申請個專利了。

另一個HTTP常用的優化就是壓縮了,網絡傳輸時間 = 消息大小/網速 既然網速比較貴那麼就壓縮一下吧,大部分服務器都會對HTTP消息進行gzip壓縮。可以在Http Header中看到,具體的就不細說了。

未來協議 SPDY

上面的都是傳統做法,下面講一個未來的技術。由於HTTP協議是上個世紀制定的協議了,已經不能很好的適應現在Web的發展,所以Google提出了SPDY協議目前是指定中的HTTP2.0標準的一個底版。SPDY主要有下面的特點:

  1. 一個TCP連接上並行多個HTTP連接,減少連接的建立時間

  2. 請求優先級(目前還沒看到具體實現)

  3. HTTP頭部壓縮,上文提到的HTTP壓縮是對HTTP body的壓縮,並沒有對頭部壓縮。對於小的HTTP消息,頭部的比重還是很大的,而現在的web中存在大量小消息。

  4. Server push/hint 服務器主動推送對象(可以想象成服務器幫客戶端預取)

業界目前對SPDY是有贊有彈,博主也持謹慎的態度。主要在1和4上,4其實和之前提到的HTTP直接預取的矛盾點一樣,萬一推送的不需要又佔據了帶寬怎麼辦,hint到底該如何實現都有困難。第一條潛在的風險就是TCP連接中途斷開,那麼所有的連接就全部停掉了,PC互聯網這種情況可能會少一些,但是移動互聯網中TCP連接斷開的情況還是比較常見的。不過作爲一個未來的技術還是有必要關注一下。

總結

上面就是博主對”從輸入 URL 到頁面加載完的過程中都發生了什麼事情“兩端之間網絡連接這塊所知道的事情還有優化措施,歡迎大家來拍磚。對於瀏覽器端到底做了些什麼博主其實也很熟,只是這一塊已經有很多成熟的資料了比如這裏這裏這裏想寫點不一樣的東西太難了。服務器端的事情博主就不是太清楚了,還請大家多多指教。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章