【轉】關於大型網站技術演化的思考(二十)--網站靜態化處理—web前端最佳化—中(12)

來源:互聯網
上載者:User

標籤:

  Web前端很多最佳化原則都是從如何提升網路通訊效率的角度提出的,但是這些原則使用的時候還是有很多陷阱在裡面,如果我們不能深入理解這些最佳化原則背後所隱藏的技術原理,很有可能掉進這些陷阱裡,最終沒有達到最佳的預期效果,今天我在這裡分析下瀏覽器和服務端通訊的一些細節問題,希望通過分析這些細節問題,能給大家一個啟迪,能更好的理解這些最佳化原則背後的隱秘,最終能更好的運用這些原則。

  網站的通訊技術是構建在http協議上,http協議底層通訊手段使用的是tcp/ip協議,但是tcp通訊協議在建立串連和中斷連線這兩個動作上是非常消耗通訊效能的,這主要是因為tcp/ip協議在串連建立時候的三向交握機制和中斷連線時候的四次揮手機制所致,我們來看看下面的圖形:

  圖中中間被紅色標記的方塊就是tcp/ip協議在建立串連時候需要發送三次報文才能確認串連是否建立成功,中間四個藍色的方框就是說明tcp/ip協議在中斷連線時候要發四次報文才能確定串連最終被斷開,而一個具體的http請求和響應也就發送兩次報文,這也就說明如果瀏覽器每次和服務端的互動都要建立和關閉一個tcp/ip串連,那麼瀏覽器和伺服器之間就要往返9次報文通訊,而真正用來處理使用者請求的報文確只有其中的兩次,換句話說這樣的一個請求大概會有80%左右的效能都不是用來處理業務需求,等於是損失了80%左右的效能,當然這個比率是9次報文互動的資料大小一致情況下得出的,如果使用者業務請求和響應的資料量比較大,那麼建立串連和中斷連線的效能損失佔比會降低,不過就算佔比降低了那也是在請求處理本身的時間變的更慢的基礎上的降低,要是瀏覽器和伺服器之間的距離特別大,那麼多出來的7次報文交換的效率問題就更加嚴重了,不管怎樣,tcp/ip的三向交握機制和四次揮手機制只要發生都會對網路請求效率產生重大影響。

  為瞭解決這個報文互動次數過多的問題,http協議本身也發生了改變,那就是http開始採用了長串連,使用長串連後網站只需要開啟一個長串連,在使用者關閉瀏覽器關閉之前瀏覽器裡的網頁都會複用這個長串連。不過http協議的1.0版本預設是不啟用長串連的,所以在使用http協議1.0版本時候我就得手動的開啟長串連,這個方法就是在http頭裡設定Connection: Keep-Alive,而http1.1版本裡長串連是預設開啟的,所以不需要我們手動的設定,而且時下的瀏覽器幾乎都支援http1.1協議,因此大多時候情況下我們是沒有必要手動去開啟長串連的。

  雖然http協議採用長串連後可以減少網站通訊時候三向交握和四次揮手的次數,但是長串連建立起來後需要瀏覽器和伺服器長時間維護,這本身會消耗瀏覽器和伺服器的效能,特別是伺服器端長時間維護長串連本身還會損壞伺服器處理並發的能力,所以早期瀏覽器會限制http1.1開啟串連的數量,例如ie7這個古董瀏覽器,它准許http1.1最多開啟2個長串連,而http1.0因為預設使用短串連它預設可以開啟4個,下面有張圖可以說明,如下所示:

  提升瀏覽器載入效率的手段除了提升每個串連的傳輸效率外,其實還有一種方式,這個方式就是使用多個串連進行並行載入,這個等於幾個人聯合起來一起完成一個任務,那麼效率肯定就比一個人高,而頁面載入時候很符合使用並發載入的情境,例如我們讓頁面裡的圖片並行載入肯定會比一個個載入圖片的效率要高多了。回到瀏覽器支援的串連數的問題,由於早期瀏覽器在http1.0和http1.1串連數的差異,某些網站例如維基百科這樣的網站,它的靜態資源特別多,為了充分發揮並發的優勢,它將存放這些靜態資源的伺服器採用http1.0協議,這樣就能並行載入更多的靜態資源,因為這個並行載入的總體效率提升相比tcp/ip握手和揮手的損失要高的多,不過現在這個手法已經起不到什麼作用了,因為新版的瀏覽器已經把兩種版本的http協議支援的串連數調整一致了,因為長串連可以複用鏈路,因此使用長串連的效率會比非長串連更好。

  上面串連數也是有一個限制的,這個限制就是必須是在同一個網域名稱下,如果一個頁面某些靜態資源放在不同網域名稱下面,那麼這個做法就可以增加頁面裡的並發數量,例如我們把一些不是經常變化的靜態資源例片、外部的css檔案以及javascript檔案單獨放置在一個靜態資源伺服器上,靜態資源伺服器對外的url地址和頁面本身的url地址不在同一個網域名稱下,那麼頁面本身的並發載入串連數就會增加一倍,不過這也就意味著瀏覽器端要維護的長串連數會變得更多,雅虎工程師曾經總結過一個頁面裡合理的網域名稱數量,那就是兩個,這個結論的提出已經過去了好多年了,現在的瀏覽器和伺服器的效能已經今非昔比了,這個跨域數量應該可以增加點,不過我個人認為一個頁面的裡包含的網域名稱數量還是不要太多,其實如果我們web前端最佳化手段使用得當,兩個不同網域名稱就足夠用了,多了價值不大,除非你網站情況是在特殊,例如你看看現在瀏覽器本身支援的串連數量已經很高了,大部分都是6,ie9甚至還達到了10,翻個倍就有12和20個串連數,我們在翻個倍就是24和40個,這個數字看起來就很恐怖了,一個電腦支援這麼多並發,假如你在瀏覽器還開啟個網站也是這麼乾的,那麼瀏覽器的並發數多的實在太嚇人了,我估計到時電腦本身就跑不動了,所以10多個串連數很夠用了,你合理髮揮下這些串連數網站的效能就能有很大提升,再說了一個網站並發串連數太多那本身就說明了你在減少http個數這個手段沒有運用好。

  回到web前端最佳化的手段,我們如果把這些手段再仔細分析下就會發現很多手段使用都是在同步請求這個情境下進行了,當然這些手段在合適情況下也能作用於非同步載入情境,但是非同步載入情境發生並發載入之前需要一個單線程的非同步載入,這個單線程的非同步載入就和分布式系統裡的單點故障有點像了,它很有可能是整個流程的軟肋所在,所以合理使用同步請求還能讓非同步作業效能更加優秀做好準備。上面我講到瀏覽器在同一個網域名稱下最多可以開啟多少個串連數,但是從事web前端開發的人都能感覺到,我們做頁面開發時候其實是沒法控制這個串連數的,那麼問題來了,這麼多串連到底是在什麼條件下被開啟的呢?這個問題非常有意思的,我們來看下面的瀑布圖:

  從上面的瀑布圖我們發現,並行下載的是圖片,這個推而廣之要是我們看見某些網站的網頁做過並發最佳化處理的設計,我們就會發現並發的資源都是純靜態資源,那麼這個並發串連數跟我們頁面的設計存在一個怎樣的關係呢?首先我們總結一下頁面裡的靜態資源,在頁面裡靜態資源有html,如果html裡面有內聯的css代碼和javascript代碼,那麼這些代碼也會歸屬於html,除了html外還有外部的css檔案、外部的javascript檔案和頁面裡使用到的圖片,那麼這些要素怎樣會促發頁面的並行載入了,換個說法這些要素又是如何促使瀏覽器同時開啟更多串連呢?

  首先我們要明確一個問題,瀏覽器之所以可以開啟更多串連數,讓這麼多串連並存執行是有個前提的,這個前提就是這些資源是不是被並行載入的,例如像外部css檔案,圖片這樣的資源,這些資源下載完畢後馬上就可以使用,因為它們下載完畢後沒有邏輯性問題要處理因此下載完畢後就可以直接拿來使用,因此它們並行載入不會影響到頁面的展示問題,這個情況如果碰到javascript就有點麻煩了,外部javascript代碼是包含邏輯在裡面,而且有些邏輯很有可能會影響頁面的展示,所以javascript下載完畢後,瀏覽器就得馬上執行,所以我們就會看到這樣的瀑布圖,如所示:

  上面的空白區就是瀏覽器在執行javascript代碼所要花費的時間。瀏覽器開啟多少個串連是瀏覽器自發的行為,這個自發行為主要出於提升瀏覽器並發下載效率的角度出發的。由於現在瀏覽器的串連基本都是採取的是http1.1協議,也就是使用的長串連,那麼串連建立後這個串連就會長期維護,如果這個長串連是單獨的靜態資源伺服器上的長串連,這個問題倒沒什麼,如果這個長串連放在主網域名稱下面,問題就來了,主網域名稱在頁面初始化載入時候會用來下載html,如果我們為提高並發下載效率,讓這個主網域名稱下還放置其他的靜態資源,那麼可能會導致瀏覽器和主網域名稱的伺服器下維護更多的長串連,而頁面後續操作基本是使用ajax來操作的,而ajax往往只會複用其中一個長串連,那麼其他多餘的長串連等於要空轉了,這個空轉還需要消耗瀏覽器和伺服器的系統資源,所以我們發現主網域名稱下的請求資源類型一定要認真加以控制,能遷移到單獨的靜態資源伺服器上的一定要進行遷移,盡量讓主網域名稱下處理的請求都是包含商務邏輯的請求,這樣就可以有效提升系統資源的使用率。這個問題進一步思考下去,我們就會發現如果服務端的業務應用伺服器之前放置一個反向 Proxy,反向 Proxy都是使用靜態資源伺服器,而靜態資源伺服器對並發的承載能力是遠超業務應用伺服器,如果主網域名稱下我們不小心放置了太多靜態資源,要是後台使用了反向 Proxy,那麼反向 Proxy也可以減輕這種長串連所造成的計算資源損失。

  上面這些情境都是在瀏覽器同步請求下進行了,那麼換到非同步請求這個並行載入靜態資源的手段還有效嗎?回答這個問題前,我們首先要想想非同步載入會導致新的靜態資源被載入嗎?這個當然可能,特別是在前端MVC的情境下,我們會把模板技術放到瀏覽器端完成,這個時候有些html模板一開始可能會包含在javascript代碼裡,作為一個變數儲存下來,而這個模板裡很有可能包含好多新的圖片被使用,當ajax從服務端擷取資料後,解析了這個模板,然後我們把構造好的模板加入到頁面的DOM結構裡,瀏覽器重新渲染頁面時候看到很多新圖片需要載入,就有可能會開啟多個串連進行並行載入來提升資源載入效率,如果碰到通過ajax技術動態載入外部CSS檔案,那麼這個並行載入情況就會更加突出了,因為css檔案裡很有可能包含大量的圖片資源,如果我們把不變的靜態資源都放置在了單獨的靜態資源伺服器,那麼這個並行載入就不會在主網域名稱下開啟更多長串連,由此可見,將靜態資源使用單獨的網域名稱的靜態資源伺服器處理的好處非常之多。

  現在http2.0協議還在起草之中,http2.0如果落地將會給web前端最佳化技術產生重大影響,http2.0打算在一個頁面裡只使用一個tcp/Ip串連,不過http2.0會在這個串連上進行鏈路複用,也就是讓一個串連上也能做到並行操作,讓串連的利用率更高,如果http2.0落地後,web前端裡那些用於減少http串連數的手段都會失去市場了,因為協議本身就能處理好並發的問題了,到時像外部css檔案,外部javascript檔案,css sprite技術說不定就要成為曆史了。

  看來本主題又寫不完了,下篇接著寫吧,今天是元宵節,這裡我祝大家節日快樂。

 

原來連結:http://www.cnblogs.com/sharpxiajun/p/4316840.html

【轉】關於大型網站技術演化的思考(二十)--網站靜態化處理—web前端最佳化—中(12)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.