從網絡通信角度談web性能優化


衡量一個網站的性能有多個指標,DNS解析時間,TCP鏈接時間,HTTP重定向時間,等待服務器響應時間等等,從用戶角度來看,就可以歸結為該網站訪問速度的快慢。也就是說性能等於網站的訪問速度。
早些年Amazon曾經做過一個統計:網頁加載時間每延長1秒鍾,一年將減少16億美元的營收。(16億美元是一個什么概念呢?2015年,百度全年的總營收約100億美元!)。
鑒於性能的重要性,於是我們便經常看到許多記錄提升訪問速度的方法的文章:減少http請求,雪碧圖,壓縮文件等等,看了這些文章后,博主了解了一些比較普遍的提升性能的方法,但是還不明白為啥這樣能提升速度呀!
作為一名有志青年,博主認為,不僅要知其然,還要知其所以然。在查閱大量書籍和博文后,終於明白了其中的玄機,特此記錄下來,與大家分享。

接下來,我們首先來深入理解一個瀏覽器與互聯網的通信過程,然后分析每個過程所占時間的多少,以及哪些過程的時間是可以減少的,再說明通過怎樣的方法可以減少這些時間,以此來縮小網站總的加載時間,提升網站的訪問速度。

從輸入url到瀏覽器開始渲染頁面中間都發生了什么

互聯網內各網絡設備間的通信都遵循TCP/IP協議,利用TCP/IP協議族進行網絡通信時,會通過分層順序與對方進行通信。分層由高到低分別為:應用層、傳輸層、網絡層、數據鏈路層。發送端從應用層往下走,接收端從數據鏈路層網上走。如圖所示:

  1. 在瀏覽器中輸入url
    用戶輸入url,如https://www.zhihu.com。其中https是協議,//后面的是網絡地址,網絡地址指出了請求的資源在哪個計算機上。網絡地址可以是IP地址,也可以是域名,這里是域名,域名更方便記憶

  2. 瀏覽器查詢緩存
    如果存在有效的緩存,則跳至第11步的渲染階段。

  3. 應用層DNS解析域名
    域名是為了方便人類記憶,但計算機不能很好的處理域名,因為IP地址的長度是固定的32位(IPv6是128位),而域名的長度不固定,機器處理起來比較困難,因此需要有一個輔助系統提供域名到IP地址的映射,這個輔助系統就是DNS(Domain Name System)。 在收到一個域名后,客戶端會先檢查本地是否有對應的IP地址,若找到則返回響應的IP地址。若沒找到則請求上級DNS服務器,直至找到根域。最終得到域名對應的IP地址,存在負載均衡時同一域名返回IP可能不同,所以IP地址才是是計算機在網絡中的唯一標識。

  4. 應用層發送http請求
    http協議是用於客戶端與服務器端通信的一種協議,它是通過請求和響應這種方式來實現通信的。HTTP請求包括請求報頭和請求主體兩個部分,其中請求報頭包含了至關重要的信息,比如請求的方法(GET,POST,PUT,DELETE,CONNECT...)、目標url、遵循的協議(http / https / ftp…),以及客戶端是否發送cookie等。

  5. SSL/TLS安全傳輸協議
    它是位於傳輸層之上的一個安全套接層也就是https中的's',確保了(1)所有信息都是加密傳播的,第三方無法竊聽(2)具有校驗機制,一旦被篡改,通信雙方會立刻發現(3)配備身份證書,防止身份被發現。
    為網絡通信提供安全保障。

  6. 傳輸層用TCP協議傳輸報文
    位於傳輸層的TCP協議為傳輸報文提供可靠的字節流服務。它為了方便傳輸,將大塊的數據分割成以報文段為單位的數據包,並為他們編號,方便服務器接收時能正確的快速還原報文信息。TCP協議通過三次握手來建立連接,通過四次揮手斷開連接,保證了傳輸的安全可靠,下面的兩張圖和那后地解釋了三次握手和四次揮手。


(圖片來源於http://www.cnblogs.com/zmlctt/p/3690998.html)

  1. 網絡層IP協議查詢MAC地址
    IP協議的作用是把TCP分割好的各種數據包傳送給接收方,這時就需要接收方的MAC 地址,也就是物理地址。IP地址和MAC地址是一一對應的關系,一個網絡設備的IP地址可以更換,但是MAC地址一般是固定不變的。ARP協議可以將IP地址解析成對應的MAC地址。當通信的雙方不在同一個局域網時,需要多次中轉才能到達最終的目標,在中轉的過程中需要通過下一個中轉站的MAC地址來搜索下一個中轉目標,路由提供這種中轉服務

  2. 數據到達數據鏈路層被處理包裝

在找到對方的MAC地址后,就將數據發送到數據鏈路層,數據鏈路層負責三件事:封裝成幀,透明傳輸,差錯檢測。

  1. 物理層傳輸到達服務器端
    數據進入物理層到達服務器后,再經歷3-7的相反操作:在鏈路層接收到數據包,再層層向上直到應用層。這過程中包括在運輸層通過TCP協議將分段的數據包重新組成原來的HTTP請求報文。

  2. 服務器響應
    服務接收到客戶端發送的HTTP請求后,查找客戶端請求的資源,並返回響應報文,響應報文中包括一個重要的信息——狀態碼。狀態碼由三位數字組成,其中比較常見的是200 OK表示請求成功。301表示永久重定向,即請求的資源已經永久轉移到新的位置。在返回301狀態碼的同時,響應報文也會附帶重定向的url,客戶端接收到后將http請求的url做相應的改變再重新發送。

  3. 客戶端接收響應並渲染頁面
    服務器的響應到達客戶端后,瀏覽器會根據接收到的數據渲染頁面。渲染階段也有許多改善性能的方案,本文的重點不在這里,下次在另一篇文章里細說。

以上就是網絡通信的整個過程,深究起來極其復雜,用到的協議也是非常多,不得不由衷地佩服先人的智慧!

chrome開發者模式Network下分析各個過程對應時間

chrome瀏覽器下按F12打開開發者工具,找到第四欄的network,在瀏覽器上方地址欄輸入一個自己從未訪問過的url,目的是保證請求的內容沒被緩存在本地(為此,博主還清理了一波瀏覽器緩存(;′⌒`),傷心)。
整體大概是這樣:

找一個有代表性的請求,如上圖紅色框所示,將鼠標放在黃色箭頭所指的地方,會浮現該請求timeline的詳情,如下圖所示

這張詳情圖中可謂是藏了不少有價值的信息呢( •̀ ω •́ )✧,注意看咯!

  1. Resource scheduling(紅色圈圈3)
    第一部分首先是資源調度的時間。
    紅色圈圈告訴我們Queued at 214.06ms,在214.06 ms 時開始排隊。排了0.57ms后(圈圈4),就Started at 214.63ms(圈圈2),也就是說資源調度結束后就開始處理該指令了。
    據chrome官方解釋,導致Queueing的原因有以下幾種:
  • 請求已被渲染引擎推遲,因為該請求的優先級被視為低於關鍵資源(例如腳本/樣式)的優先級。 圖像經常發生這種情況。
  • 請求已被暫停,以等待將要釋放的不可用 TCP 套接字。
  • 請求已被暫停,因為在 HTTP 1 上,瀏覽器僅允許每個源擁有六個 TCP 連接。
  • 生成磁盤緩存條目所用的時間(通常非常迅速)
  1. Connection Start(圈圈5)
    資源調度后就要開始建立鏈接了。
    圈圈6 Stalled代表 請求等待發送所用的時間,此時間包含第一部分中的第二步:查看瀏覽器緩存所用的時間,下圖是刷新后一個“from disk cache”文件的詳情圖,可以很好地證明這一點。

圈圈7 Proxy negotiation 代表與代理服務器協商的時間
圈圈8 DNS Lookup 執行 DNS 查詢所用的時間。 頁面上的每一個新域都需要完整的往返才能執行 DNS 查詢。對應於第一部分中的“應用層DNS解析域名”時間
圈圈9 Initial Connection 初始化連接所用的時間,包括 TCP 握手/重試和協商 SSL 的時間。對應於第一部分的6和7
圈圈10 SSL 完成SSL握手所需要的時間,對應於第一部分的5

機智的你是不是已經發現建立鏈接的時間剛好對應於第一部分中的3-

  1. Request/Response
    通信鏈接建立后,就可以發送請求了,服務器處理后返回響應,客戶端再根據響應內容下一步處理

圈圈11 Request sent 發送請求的時間,這個是非常快的
圈圈12 Waiting(TTFB)等待服務器初始響應所用的時間,也稱為至第一字節的時間。 此時間將捕捉到服務器往返的延遲時間,以及等待服務器傳送響應所用的時間。
最后是 Content Download,接受(下載)響應數據所需要的時間。

可以發現,詳情圖中的時間順序和第一張網絡模型示意圖剛好一一對應,只有TCP/IP連接建立完成后,才能再建立SSL/TLS,最后才可用http協議請求/響應。

到這里,想必你已經明白了一次完整的請求需要經歷的步驟和耗費的時間,那么這些時間中有哪些是可以人為減少的呢?我們可以通過怎樣的方式來減少這些時間來提高性能呢?
看下面

優化web性能的若干方法

  1. 減少http的請求數降低connection的時間
    由上面的詳情圖可以看到,如果本地沒有緩存時,許多時間都花在了第二步Connection Start 建立鏈接上,只有少部分花在了Content Download上。那好,現在如果我們把兩個文件合並成一個,就可以用一次請求代替之前的兩次請求,理論上是不是就節約了一次Connection的時間了?合並的文件越多,節約的時間就越多。
    所以我們可以把圖片,css,js等一些可以合並的文件盡量合並來減少http的請求數,降低總的connection的時間。
    細心的朋友可能會發現,有的請求是幾乎沒有connection的時間的,它們的詳情圖長這樣:

查看request header發現其中有一個這樣的鍵值對:

對,就是因為它,http的keep-alive可以在一定的時間內保證連接的可復用性,減少連接時間,但它的期限是有限的,可以看到network下的請求中還是有若干次請求是有connection的時間的,所以合並文件還是必須的。

  1. 壓縮文件降低content download的時間
    上圖中content download的時間不算多,只有20.47ms ,但它還是可以被減少的呀,如果我們壓縮了該文件,在相同物理環境下,它會變得更少呀!能減少一點是一點嘛。
    而且在一些項目中,部分文件可達幾百kb,這時content download的時間就不止20ms了,所以壓縮后還是能減少不少時間的。
    所以項目上線前,像一些圖片啦,css,js啦,能壓縮的還是盡量壓縮。

  2. 使用瀏覽器緩存
    把網站里面更新頻率比較低的靜態資源緩存在瀏覽器中,能夠很好地提升速度。事實證明的確如此,( •̀ ω •́ )✧

畢竟對於幾百K的文件硬盤還是可以秒讀的嘛。
通過設置 http 頭里的 Cache-Control 和 Expires 屬性來設定瀏覽器緩存時間,另外還有 Etags 和 opcode 的緩存,根據具體情況進行選擇吧

  1. 減少DNS查找
    DNS用於映射主機名和IP地址,一般一次解析需要20~120毫秒。瀏覽器會首先根據頁面的主機名進行域名解析,在有ISP返回結果之前頁面不會加載任何內容,所以減少DNS查找可以有效降低等待時間。為達到更高的性能,DNS解析通常被多級別地緩存,如由ISP或局域網維護的caching server,本地機器操作系統的緩存(如windows上的DNS Client Service),瀏覽器。IE的缺省DNS緩存時間為30分鍾,Firefox的缺省緩沖時間是1分鍾。 我們能做的是盡量減少一個頁面的主機名,但要在瀏覽器最大並行下載數跟dns查找之間做權衡。根據雅虎的研究,最好將主機名控制在2-4個內。

  2. CDN加速
    CDN 的本質也屬於緩存,內容分發網絡,把數據緩存在里用戶近的地方,使用戶盡快的獲取數據。
    CDN 通常是部署在網絡運營商的機房,這些運營商為用戶提供網絡服務,因此用戶請求的路由會優先到達 CDN 服務器,如果存在請求的資源的話,就直接返回,以最短路徑返回響應,提高了用戶訪問速度,同時還能夠為中心機房減輕壓力。其原理如下:

CDN 一般用來緩存靜態資源,如css,Script腳本,靜態頁面,圖片等,這些內容修改頻率很低但是訪問請求頻率很高,因此放在 CDN 上能夠很好的改善訪問速度

  1. 減少重定向
    重定向是指將一個URL重新路由到另一個URL。瀏覽器會自動重定向請求到Location指定的URL上,也就說把之前的過程又重復一遍才能請求到真正的資源,會極大地降低用戶體驗。

好了,到此本文的主要內容已全部完結了。
本文是博主在學習過程中的一個總結,特此記錄下來備忘,也希望對其他小伙伴有所幫助。其中如有敘述不當之處,還望您能指出,一起探討~

博客原文地址:Claiyre的個人博客 https://claiyre.github.io/
博客園地址:http://www.cnblogs.com/nuannuan7362/
如需轉載,請在文章開頭注明原文地址

參考:(http://www.cnblogs.com/dojo-lzz/p/4591446.html)[http://www.cnblogs.com/dojo-lzz/p/4591446.html]
(http://seanlook.com/2015/01/07/tls-ssl/)[http://seanlook.com/2015/01/07/tls-ssl/]
(https://segmentfault.com/a/1190000007624980)[https://segmentfault.com/a/1190000007624980]


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM