摘要:套接字按池組織,按原點分組,每個池強制實施自己的連接限制和安全約束。待處理的請求排隊,優先,然后綁定到池中的單個套接字。
就像我們之前文章中提到的渲染引擎一樣,我們認為好的和優秀的JavaScript開發人員之間的區別在于,后者不僅了解語言的基本要素,還要了解其內部原理和周圍環境。
歷史四十九年前,創建了一個名為ARPAnet的東西。這是一個早期的分組交換網絡,也是實現TCP / IP套件的第一個網絡。該網絡在加州大學和斯坦福研究院之間建立了聯系。 20年后,Tim Berners-Lee發布了一個名為“Mesh”的提案,該提案后來更為人稱為萬維網。在那49年里,互聯網已經走過了漫長的道路,從兩臺計算機交換數據包開始,到達超過7500萬臺服務器,38億人使用互聯網和1.3B網站。
在這篇文章中,我們將嘗試分析現代瀏覽器采用哪些技術來自動提升性能,并且我們將特別放大瀏覽器網絡層。最后,我們將提供一些關于如何幫助瀏覽器提升Web應用性能的想法。
概觀現代網絡瀏覽器專為快速,高效和安全地交付網絡應用/網站而設計。數百個組件運行在不同的層上,從流程管理和安全沙箱到GPU流水線,音頻和視頻等等,Web瀏覽器看起來更像是一個操作系統,而不僅僅是一個軟件應用程序。
瀏覽器的整體性能取決于許多大型組件:解析,布局,樣式計算,JavaScript和WebAssembly執行,渲染,當然還有網絡堆棧。
工程師經常認為網絡堆棧是一個瓶頸。這通常是這種情況,因為在解除其他步驟之前,需要從互聯網獲取所有資源。為了提高網絡層的效率,它不僅需要扮演簡單的套接字管理員的角色。它作為一種非常簡單的資源獲取機制呈現給我們,但它實際上是一個擁有自己的優化標準,API和服務的整個平臺。
作為Web開發人員,我們不必擔心單個TCP或UDP數據包,請求格式化,緩存和其他所有事情。整個復雜性由瀏覽器處理,因此我們可以專注于我們正在開發的應用程序。但是,了解發生了什么,可以幫助我們創建更快,更安全的應用程序。
實質上,用戶開始與瀏覽器交互時發生了以下情況:
用戶在瀏覽器地址欄中輸入一個URL
給定Web上資源的URL,瀏覽器首先檢查本地和應用程序緩存,并嘗試使用本地副本來完成請求。
如果緩存無法使用,瀏覽器將從URL中獲取域名,并從DNS請求服務器的IP地址。如果該域被緩存,則不需要DNS查詢。
瀏覽器會創建一個HTTP數據包,說明它請求位于遠程服務器上的網頁。
數據包被發送到TCP層,在TCP數據包的頂部添加它自己的信息。此信息是維護啟動會話所必需的。
然后將數據包交給IP層,主要工作是找出將數據包從用戶發送到遠程服務器的方式。這些信息也存儲在數據包的頂部。
數據包被發送到遠程服務器。
一旦收到數據包,就會以類似的方式發送回應。
W3C Navigation Timing規范提供瀏覽器API以及瀏覽器中每個請求的生命周期背后的時間和性能數據。讓我們來看看這些組件,因為它們在提供最佳用戶體驗方面起著至關重要的作用:
整個聯網過程非常復雜,有許多不同的層次可能會成為瓶頸。這就是為什么瀏覽器努力通過使用各種技術來提高性能的原因,以便整個網絡通信的影響最小。
套接字管理讓我們從一些術語開始:
Origin - 應用協議,域名和端口號(例如https,www.example.com,443)
套接字池 - 屬于同一Origin的一組套接字(所有主流瀏覽器都將最大池大小限制為6個套接字)
JavaScript和WebAssembly不允許我們管理單個網絡套接字的生命周期,這是一件好事!這不僅可以讓我們的手保持清潔,而且還可以讓瀏覽器自動進行大量的性能優化,其中一些包括套接字重用,請求優先級和后期綁定,協議協商,強制連接限制等等。
實際上,現代瀏覽器會花費更多的時間來將請求管理周期與套接字管理分開。套接字按池組織,按原點分組,每個池強制實施自己的連接限制和安全約束。待處理的請求排隊,優先,然后綁定到池中的單個套接字。除非服務器有意關閉連接,否則可以在多個請求中自動重用相同的套接字!
由于新的TCP連接的開通需要額外的成本,因此連接的重復使用對其本身具有很大的性能優勢。默認情況下,瀏覽器使用所謂的“keepalive”機制,這可以節省在發出請求時打開新連接到服務器的時間。打開一個新的TCP連接的平均時間是:
本地請求 - 23ms
橫貫大陸的請求 - 120毫秒
洲際請求 - 225毫秒
這種架構打開了其他一些優化機會的大門。這些請求可以根據其優先級以不同的順序執行。瀏覽器可以優化所有套接字上的帶寬分配,或者可以在預期請求時打開套接字。
正如我之前提到的,這一切都是由瀏覽器管理的,并不需要我們的任何工作。但這并不一定意味著我們無能為力。選擇正確的網絡通信模式,傳輸類型和頻率,選擇協議以及調整/優化服務器堆棧可以在提高應用程序的整體性能方面發揮重要作用。
有些瀏覽器甚至更進一步。例如,Chrome可以自我教導自己在使用它時變得更快。它根據訪問的網站和典型的瀏覽模式進行學習,以便在用戶做任何事情之前預測可能的用戶行為并采取行動。最簡單的例子是當用戶在鏈接上懸停時預先呈現頁面。如果您有興趣了解更多關于Chrome優化的信息,請參閱本章的https://www.igvita.com/posa/h...。
網絡安全和沙盒允許瀏覽器管理單個套接字具有另一個非常重要的目的:通過這種方式,瀏覽器可以對不可信的應用程序資源執行一致的安全和策略約束。例如,瀏覽器不允許直接API訪問原始網絡套接字,因為這可以使任何惡意應用程序與任何主機進行任意連接。瀏覽器還強制執行連接限制,以保護服務器以及客戶端免受資源耗盡。
瀏覽器格式化所有傳出請求,以強化一致且格式良好的協議語義來保護服務器。同樣,響應解碼自動完成,以保護用戶免受惡意服務器的侵害。
TLS談判傳輸層安全性(TLS)是一種通過計算機網絡提供通信安全性的加密協議。它在許多應用程序中廣泛使用,其中之一是網頁瀏覽。網站可以使用TLS來保護其服務器和Web瀏覽器之間的所有通信。
整個TLS握手由以下步驟組成:
客戶端向客戶端發送“Client hello”消息,以及客戶端的隨機值和支持的密碼套件。
服務器通過向客戶端發送“服務器問候”消息以及服務器的隨機值進行響應。
服務器將其證書發送給客戶端,并可以向客戶端請求類似的證書。服務器發送“服務器已完成”消息。
如果服務器已經從客戶端請求證書,則客戶端發送它。
客戶端創建一個隨機的預主密鑰,并使用服務器證書中的公鑰對其進行加密,并將加密的預主密鑰發送給服務器。
服務器收到預主密鑰。服務器和客戶端根據預主密鑰生成主密鑰和會話密鑰。
客戶端向服務器發送“更改密碼規格”通知,指示客戶端將開始使用新的會話密鑰進行散列和加密消息。客戶端還發送“客戶端已完成”消息。
服務器收到“更改密碼規范”并使用會話密鑰將其記錄層安全狀態切換為對稱加密。服務器向客戶端發送“服務器已完成”消息。
客戶端和服務器現在可以通過他們建立的安全通道交換應用程序數據。所有從客戶端發送到服務器并返回的消息均使用會話密鑰加密。
如果任何驗證失敗 - 例如服務器正在使用自簽名證書,則警告用戶。
如果兩個頁面的協議,端口(如果指定了一個)和主機相同,則兩個頁面具有相同的來源。
以下是可能嵌入跨源的資源的一些示例:
帶有