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