萬盛學電腦網

 萬盛學電腦網 >> 網頁制作 >> Html5 >> web前端優化的方法

web前端優化的方法

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

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

web前端優化

圖中中間被紅色標記的方塊就是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個,下面有張圖可以說明,如下所示:

web前端優化

提升浏覽器加載效率的手段除了提升每個連接的傳輸效率外,其實還有一種方式,這個方式就是使用多個連接進行並行加載,這個等於幾個人聯合起來一起完成一個任務,那麼效率肯定就比一個人高,而頁面加載時候很符合使用並發加載的場景,例如我們讓頁面裡的圖片並行加載肯定會比一個個加載圖片的效率要高多了。回到浏覽器支持的連接數的問題,由於早期浏覽器在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前端開發的人都能感覺到,我們做頁面開發時候其實是沒法控制這個連接數的,那麼問題來了,這麼多連接到底是在什麼條件下被開啟的呢?這個問題非常有意思的,我們來看下面的瀑布圖:

web前端優化

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

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

web前端優化

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

copyright © 萬盛學電腦網 all rights reserved