天天看點

【我寫的】面試官一上來就問我Chrome底層原理和HTTP協定(萬字長文)

前言

有人說,如果你懂得浏覽器的工作原理,你就能解決80%的前端難題。

是的,了解浏覽器的工作原理,有助于你的工作;而了解TCP/IP 、HTTP等網絡協定,更是對你未來的職業發展大有裨益。

下面,我總結了4個面試常考的關于浏覽器和網絡通信的問題,為你重新梳理浏覽器,網絡通信、頁面渲染、JavaScript、浏覽器安全等知識,進而讓你對整個前端後端體系有全新的認識。

第一問:Chrome為什麼打開一個頁面,會有4個程序?

學習掌握:浏覽器中的網絡流程,頁面渲染過程,JavaScript執行流程,以及Web安全理論。下面展開問題了解多程序架構:

多程序架構的學習

程序和線程的概念混淆

從計算的角度來說,單線程就是一個接一個的計算,多線程就是同時處理多個計算。多線程是指程式中包含多個執行流,即在一個程式中可以同時運作多個不同的線程來執行不同的任務,就是說允許單個程式建立多個并行執行。

單線程是程式中的一個執行流,每個線程都有自己的專有寄存器(棧指針、程式計數器等),但代碼區是共享的,即不同的線程可以執行同樣的函數。

多線程也是程式,是以線程需要占用記憶體,線程越多占用記憶體也越多,多線程需要協調和管理,是以需要CPU時間跟蹤線程;線程之間對共享資源的通路會互相影響,必須解決争用共享資源的問題;線程太多會導緻控制太複雜。

單線程在程式執行時,所走的程式都是按照連續順序下來的,前面的必須處理好,才會執行後面的。多線程運作就是一個程序内有多個相對獨立的并且實作特定的任務以競争CPU的方式執行,宏觀上是并發,實際上是分時執行,隻是執行的時間片較短。

每個正在運作的程式即是程序,至少包含一個線程,這個線程叫主線程,它在程式啟動時被建立,用于執行main函數。隻有一個主線程的程式,稱為單線程程式。擁有多個線程的程式,稱為多線程程式。

程序是當一個程式開始運作時,它就是一個程序,程序包括運作中的程式和程式所使用到的記憶體和系統資源(一個程序又是由多個線程所組成的)

多線程的好處就是可以提高CPU的使用率,在多線程程式中,如果一個線程必須等待的時候,CPU可以運作其它的線程而不是等待,這樣可以大大地提高程式的效率。

是以,線程是不能單獨存在的,它是由程序來啟動和管理的,一個程序就是一個程式的運作執行個體。線程是依附于程序的,而程序中使用多線程并行處理能提升運算效率。線程之間共享程序中的資料。當一個程序關閉後,作業系統會回收程序所占用的記憶體。

目前的多程序架構浏覽器Chrome包括,1個浏覽器主程序,1個GPU程序,1個網絡程序,多個渲染程序和多個插件程序。

so,打開一個頁面,為啥有4個程序?因為打開1個頁面:至少需要1個網絡程序,1個浏覽器程序,1個GPU程序以及1個渲染程序。

雖然多程序模型提升了浏覽器的穩定性、流暢性和安全性,但是帶來了更高的資源占用,更複雜的體系架構。so,Chrome官方要建構一個更内聚,松耦合,易于維護和擴充的系統。

第二問:TCP協定是如何保證頁面檔案能被完整送達浏覽器的?

對于在網絡中,我們知道一個檔案通常會被拆分為很多資料包來進行傳輸,而資料包在傳輸過程中又有很大的可能會丢失或者出錯,保證頁面檔案完整地送達浏覽器是有必要的。

下面就這三方面展開描述:

  1. 資料包如何送達到主機
  2. 主機如何将資料包轉交給應用
  3. 資料是如何被完整地送達到應用程式

資料包從主機A送到主機B,資料包上會附加上主機B的IP位址資訊,主機A本身的IP位址,這些附加的資訊會被裝進一個IP頭的資料結構裡(包含IP版本,源IP位址,目标IP位址,生存時間等)

這些一般我們都了解,下面主要說明TCP(Transmission Control Protocol),傳輸控制協定是一種面向連接配接的,可靠的,基于位元組流的傳輸層通信協定,在簡化的計算機網絡OSI模型中,它完成第四層傳輸層所指定的功能。

使用者資料報協定(UDP)是同一層内另一個重要的傳輸協定。

在網際網路協定族中,TCP層是位于IP層之上的,TCP->IP,應用層之下的中間層,應用層->中間層。不同主機的應用層之間經常需要可靠的,像管道一樣的連接配接,但是IP層不提供這樣的流機制,而是提供不可靠的包進行交換。

TCP為了保證不發生丢包的情況,就給每個包一個序号,同時序号也保證了傳送到接收端實體的包的按序接收。接收端實體對已成功收到的包發回一個相應的确認資訊(ACK),如果發送端實體在合理的往返時延(RTT)内未收到确認,那麼對應的資料包就被假設為已丢失并進行重傳。

  • 資料在TCP層稱為流
  • 資料分組稱為分段
TCP協定的運作:連接配接建立,資料傳送,連接配接終止。

那你了解什麼是TCP嗎?這一點大部分人應該隻會說它是一種協定。

TCP傳輸控制協定是TCP/IP,傳輸控制協定Internet協定中的主要協定之一,TCP/IP是一套通信協定,用于連接配接Internet以及大多數其他計算機網絡上的主機。

協定是一種共同商定的用于執行某件事的格式。對于計算機,最常用于指一組規則,使計算機能夠互相連接配接并傳輸資料,稱為通信協定。

TCP是一種面向連接配接的協定,它在主機之間建立并維護虛拟連接配接,直到交換了一條消息或要在其上運作的應用程式交換的消息為止。資料包是TCP/IP網絡上資料傳輸的最基本機關。

TCP在傳輸層上運作,負責維護整個網絡上可靠的端到端通信,IP是網絡層協定,它是傳輸層正下方的層,在傳輸層運作的有:UDP(使用者資料報協定),RTP(實時傳輸協定),SCTP(流控制傳輸協定)。

連接配接建立

TCP用三次握手過程建立一個連接配接

三次握手協定的過程:

a.用戶端 向 伺服器端 發送一個 SYN 包,請求一個主動打開。該包攜帶用戶端為這個連接配接請求設定的随機數A作為消息列号。

b.伺服器端接收到一個SYN包後,把該包放入SYN隊列中;回送一個SYN/ACK。ACK的确認碼應為A+1,SYN/ACK包本身攜帶一個随機産生的序号B。

c.用戶端收到SYN/ACK包後,發送一個ACK的包,該包的序号被設定為A+1,而ACK的确認碼為B+1。當伺服器端收到這個ACK包的時候,把請求幀從SYN隊列中移出,放置ACCEPT隊列中。

場景:當伺服器端接收到用戶端發送過來的SYN後, 回了SYN-ACK後,用戶端掉線了,伺服器端沒有收到用戶端回來的ACK,那這個連接配接 就 處于 一個中間狀态,沒成功也沒失敗。

但是,伺服器端如果在一定時間内沒有收到TCP會重新發SYN-ACK。

  • 主機收到一個TCP包時,用兩端的IP位址與端口号來辨別這個TCP包屬于哪個session。使用一張表來存儲所有的session,表中的每條稱作TCB(Transmit Control  Block)。
  • TCB結構的定義包含:連接配接使用的源端口, 目的端口,目的ip, 序号, 應答序号, 對方視窗大小, 已方視窗大小, tcp狀态, tcp輸入/輸出隊列, 應用層輸出隊列, tcp的重傳有關變量等。
  • 伺服器端的連接配接數量是無限的,隻受記憶體的限制。
資料傳送

在每個TCP封包段中都有一對序号和确認号。

TCP封包發送者稱自己的位元組流的編号為序号,稱接收到對方的位元組流編号為确認号。通過使用序号和确認号,TCP層可以把收到的封包段中的位元組按正确的順序傳遞給應用層。

TCP協定使用序号辨別每端發出的位元組順序,從另一端接收資料可以重建順序,無懼傳輸的包的亂序傳遞或丢包。

發送确認包acks,攜帶接收對方發來的位元組流的編号(确認号),告訴對方已經成功接收的資料流的位元組位置。

資料包結構

下面讓我們來看看資料包結構圖:

【我寫的】面試官一上來就問我Chrome底層原理和HTTP協定(萬字長文)

包含:偏移位元組,來源連接配接端口,目的連接配接端口,序列号碼,确認号碼,校驗和,緊急指針等。

  • 來源連接配接端口,16位長,識别發送連接配接端口
  • 目的連接配接端口,16位長,識别接收連接配接端口
  • 序列号(seq,32位長)
  • 确認号(ack,32位長),期望收到的資料的開始序列号,也即已經收到的資料的位元組長度加1
  • 資料偏移(4位長),以4位元組為機關計算出的資料段開始位址的偏移值。
  • 保留,需置0
  • ACK—為1表示确認号字段有效
  • SYN—為1表示這是連接配接請求或是連接配接接受請求,用于建立連接配接和使順序号同步
  • FIN—為1表示發送方沒有資料要傳輸了,要求釋放連接配接
  • RST—為1表示出現嚴重差錯。可能需要重新建立TCP連接配接。還可以用于拒絕非法的封包段和拒絕連接配接請求
  • 緊急指針(16位長)—本封包段中的緊急資料的最後一個位元組的序号
  • 視窗(WIN,16位長)—表示從确認号開始,本封包的發送方可以接收的位元組數,即接收視窗大小。用于流量控制
  • 校驗和(Checksum,16位長)—對整個的TCP封包段,包括TCP頭部和TCP資料,以16位字進行計算所得。這是一個強制性的字段

記住其中IP是把資料包送達目的主機的,資料包送達到主機。那麼如何将資料包轉交給應用的呢?

UDP是把資料包送達應用程式的。

UDP是基于IP之上開發能和應用打交道的協定,使用者資料包協定,是決定把資料包交給哪個程式的,IP隻負責把資料包傳送到對方電腦。

看完位置,那麼下面我們來簡單對比一下UDP和TCP:

UDP: 無連接配接;支援一對一,一對多,多對一和多對多互動通信;對應用層傳遞的封包直接打包;盡最大努力傳遞,也就是不可靠;不使用流量控制和擁塞控制;首部開銷小,僅8位元組。

TCP:面向連接配接;每一條TCP連接配接隻能有兩個端點EP,隻能是一對一通信;面向位元組流;可靠傳輸,使用流量控制和擁塞控制;首部最小20位元組,最大60位元組。

UDP最重要的一點就是端口号,因為UDP是通過端口号把資料包分發給正确的程式,UDP不能保證資料的可靠性,但傳輸速度快。

重要的講解是:資料是如何被完整地送達到應用程式?

TCP就是把資料完整地送達應用程式。

TCP是一種面向連接配接的,可靠的,基于位元組流的傳輸層通信協定,提供重傳機制,引入了資料包排序機制(TCP頭,提供了排序的序列号,用來通過序号重排資料包)。

說到TCP連接配接,就要說說常面試的TCP/IP的三次握手,建立連接配接;四次揮手,斷開連接配接。

三次握手圖:

【我寫的】面試官一上來就問我Chrome底層原理和HTTP協定(萬字長文)

完成了三次TCP握手:

女朋友發給男朋友:“在嗎?”男朋友回複女朋友:“我在!”女朋友回複男朋友:“我知道了!”

此時男朋友知道了。

四次揮手圖:

【我寫的】面試官一上來就問我Chrome底層原理和HTTP協定(萬字長文)

完成四次揮手:

女朋友發給男朋友:“分手吧!”男朋友回複女朋友:“額?”男朋友回複女朋友:“認真的嗎?”女朋友回複男朋友:“認真的!”

此時女朋友删除了男朋友的微信。

按照我描述的三次握手和四次揮手,我相信你懂了,哈哈!

第三問:HTTP請求流程,為什麼很多站點第二次打開速度會很快呢?

說到HTTP協定,它是建立在TCP連接配接基礎之上的,超文本傳輸協定,HTTP是一種用于分布式,協作式和超媒體資訊系統的應用層協定,HTTP是網際網路的資料通信的基礎。

某人說:要想學好浏覽器,就要深入了解HTTP。

浏覽器是使用HTTP協定作為應用層協定,用來封裝請求的文本資訊,使用TCP/IP作傳輸層協定将它發到網絡上(http的内容是通過TCP的傳輸資料階段來實作的)。

  • 域名和IP位址-映射關系,域名映射為IP的系統叫作“域名系統”,簡稱DNS。

域名系統DNS是網際網路的一項服務。它作為将域名和IP位址互相映射的一個分布式資料庫,能夠使人更友善地通路網際網路。

域名如:dadaqianduan.cn (URL位址)

IP位址為:xx.233.xxs.12 (通路)

首先,第一步浏覽器會請求DNS傳回域名對應的IP,浏覽器還提供了DNS資料緩存服務,如果某個域名已經被解析過了,浏覽器就會緩存解析的結構,下次查詢時直接使用,減少一次網絡請求。拿到IP後,就需要擷取端口号,如果url沒有明确指出端口号,HTTP協定預設是80端口。

到這一步明白的清清楚楚了,IP和端口号。那麼讓我說說HTTP協定的描述,這裡補充是為了更好的了解:

HTTP是一個用戶端和伺服器端之間請求和應答的标準,通常使用TCP協定,通過使用網頁浏覽器,網絡爬蟲或者其它的工具,用戶端發起一個HTTP請求到伺服器上指定端口,預設端口為80。

應答的伺服器上存儲着一些資源,如HTML檔案和圖像等,源伺服器;(用戶端稱為使用者代理程式),使用者代理和源伺服器中間可能存在多個"中間層",比如代理伺服器,網關,隧道等。

so,HTTP伺服器在端口監聽用戶端的請求,一旦收到請求,伺服器會向用戶端傳回一個狀态,如:"HTTP/1.1 200 OK",以及傳回的内容,如請求的檔案,錯誤消息,或者其它消息。

到這裡我先回答一下:浏覽器發起HTTP請求流程:1.建構請求(建構請求行資訊);2.查找緩存(浏覽器緩存是一種在本地儲存資源副本,以供下次請求時直接使用的技術);3.準備IP位址和端口;4.等待TCP隊列;5.建立TCP連接配接;6.發送HTTP請求。

然後伺服器處理請求,伺服器傳回請求,斷開連接配接。

其實端口和IP位址準備好後,不一定直接建立TCP連接配接的,因為在Chrome中有個機制,就是同一個域名同時最多隻能建立6個TCP連接配接,如果在同一個域名下同時有10個請求發生,那麼其中就有4個請求進入排隊等待狀态。

如果請求數量少于6個,就直接進入建立TCP連接配接。

發送HTTP請求

上面都講好了初步,那麼浏覽器是如何發送請求資訊給伺服器的呢?

來一張post請求抓包圖:

【我寫的】面試官一上來就問我Chrome底層原理和HTTP協定(萬字長文)

來張浏覽器發送請求到伺服器端接收傳回的過程:

【我寫的】面試官一上來就問我Chrome底層原理和HTTP協定(萬字長文)

描述:使用者在浏覽器輸入請求的url位址,浏覽器内部的核心代碼會将這個url進行拆分解析,最終将domain發送到DNS伺服器上,DNS伺服器會根據domain去查詢相關的對應的ip位址,進而将IP位址傳回給浏覽器。

浏覽器有了ip位址後就會知道這個請求是發送到哪裡的。經過(區域網路,交換機,路由器,主幹網咯)到達伺服器。

對于經常了解HTTP的朋友應該了解上述表達,那接下來看看HTTP請求資料格式(可看上圖->來一張post請求抓包圖):

HTTP請求資料格式:

浏覽器首先向伺服器發送請求行(請求方法;請求URI;HTTP協定版本)-來告訴伺服器浏覽器需要什麼資源,常用請求方法為GET,請求頭(用來告訴一些浏覽器的基礎資訊-浏覽器所使用的作業系統、浏覽器核心等資訊,以及目前請求的域名資訊、浏覽器端的Cookie資訊等),請求體(如常用的POST,用于發送一些資料給伺服器,準備的資料是通過請求體來發送的)。

伺服器處理HTTP請求流程:

  1. 傳回請求;
  2. 斷開連接配接;
  3. 重定向。
【我寫的】面試官一上來就問我Chrome底層原理和HTTP協定(萬字長文)

檢視傳回請求資料,-i,擷取傳回響應行(包含協定版本和狀态碼),響應頭,響應體資料。

一般情況下,伺服器向用戶端傳回了請求資料,就要關閉TCP連接配接。但其頭資訊中加入了該字段:Connection: Keep-Alive,讓TCP連接配接仍然保持連接配接,可以繼續同一個TCP連接配接發送請求,可以省下次請求時需要建立連接配接的時間。

其實一般傳回請求,斷開連接配接就沒了,但有一種就是你在浏覽器中打開的url,發現最終的頁面位址不一樣,那是因為有一個重定向操作。

如圖:-I表示隻需要擷取響應頭和響應行資料

【我寫的】面試官一上來就問我Chrome底層原理和HTTP協定(萬字長文)
  • location字段時重定向的位址;

狀态碼301和302的差別

301 Moved Permanently 被請求的資源已永久移動到新位置,并且将來任何對此資源的引用都應該使用本響應傳回的若幹個URI之一。如果可能,擁有連結編輯功能的用戶端應當自動把請求的位址修改為從伺服器回報回來的位址。除非額外指定,否則這個響應也是可緩存的。

302 Found 請求的資源現在臨時從不同的URI響應請求。由于這樣的重定向是臨時的,用戶端應當繼續向原有位址發送以後的請求。隻有在Cache-Control或Expires中進行了指定的情況下,這個響應才是可緩存的。

字面上的差別:301是永久重定向,而302是臨時重定向

302重定向是暫時的重定向,搜尋引擎會抓取新的内容而保留舊的位址,因為伺服器傳回302,是以搜尋搜尋引擎認為新的網址是暫時的。

301重定向是永久的重定向,搜尋引擎在抓取新的内容的同時也将舊的網址替換為了重定向之後的網址。

接下來,讓我們梳理一下HTTP版本号,這一點,我相信在學習的過程中,大家也是想知道的。

HTTP/0.9:

已過時。僅支援請求方式GET,并且僅能請求通路HTML格式的資源,沒有在通訊中指定版本号,且不支援請求頭。

HTTP/1.0:

這是第一個在通訊中指定版本号的HTTP協定版本,增加了請求方式POST和HEAD;不再局限于0.9版本的HTML格式,根據Content-Type可以支援多種資料格式;包括狀态碼(status code)、多字元集支援、多部分發送(multi-part type)、權限(authorization)、緩存(cache)、内容編碼(content encoding)等。

1.0版本:每次TCP連接配接隻能發送一個請求,當伺服器響應後就會關閉這次連接配接,下一個請求需要再次建立TCP連接配接.

HTTP/1.1:

預設采用持續連接配接(TCP連接配接預設不關閉,可以被多個請求複用,不用聲明Connection: keep-alive),能很好地配合代理伺服器工作。

一個TCP連接配接可以允許多個HTTP請求

增加了管道機制,在同一個TCP連接配接裡,允許多個請求同時發送,增加了并發性,進一步改善了HTTP協定的效率

1.1版規定可以不使用Content-Length字段,而使用"分塊傳輸編碼"-隻要請求或回應的頭資訊有Transfer-Encoding字段,就表明回應将由數量未定的資料塊組成。Transfer-Encoding: chunked

新增了請求方式PUT、PATCH、OPTIONS、DELETE等

  • 分塊傳輸編碼:是超文本傳輸協定中的一種資料傳輸機制,允許HTTP由網頁伺服器發送給用戶端應用的資料可以分成多個部分,分塊傳輸編碼隻在HTTP協定1.1版本(HTTP/1.1)中提供。

同一個TCP連接配接裡,所有的資料通信是按次序進行的。回應慢,會有許多請求排隊,造成"隊頭堵塞"。

HTTP/2:

于2015年5月作為網際網路标準正式釋出。加了雙工模式,即不僅用戶端能夠同時發送多個請求,服務端也能同時處理多個請求,解決了隊頭堵塞的問題。

使用了多路複用的技術,做到同一個連接配接并發處理多個請求,而且并發請求的數量比HTTP1.1大了好幾個數量級。

增加伺服器推送的功能,不經請求服務端主動向用戶端發送資料。

HTTP1.1相較于HTTP1.0協定差別:

  1. 緩存處理
  2. 帶寬優化及網絡連接配接的使用
  3. 錯誤通知的管理
  4. 消息在網絡中的發送
  5. 網際網路位址的維護
  6. 安全性及完整性

最後的最後,說第二次站點的打開為啥速度快?

原因是第一次加載頁面過程中,緩存了一些耗時的資料,主要緩存有 DNS緩存 和 頁面資源緩存 兩個方面。
  • 浏覽器緩存

當第一次發送請求,伺服器傳回HTTP響應頭給浏覽器時,浏覽器會通過響應頭中CacheControl字段來設定是否緩存資源。通常還需設定一個緩存時間,Cache-Control:Max-age=2000,在緩存沒有過期的情況下,在發送請求請求該資源,會直接傳回緩存中的資源給浏覽器。如果緩存過期,浏覽器則會繼續發起網絡請求。

第四問:輸入URL到頁面展示發生了什麼?

簡單地說一下就是:

  • 浏覽器主程序送出url給網絡程序
  • 網絡程序請求伺服器,傳回響應頭行體,判斷是否需要重定向
  • 網絡程序将頁面類型的響應資源送出給渲染程序
  • 渲染程序渲染結束,加載完畢

分步驟簡單說一下就是:

  1. 首先是域名解析
  2. 建立TCP連結
  3. 建立Http請求
  4. 伺服器處理Http請求
  5. 關閉TCP連接配接
  6. 浏覽器解析資源
  7. 浏覽器渲染頁面

在我的GitHub上也講過:從浏覽器位址欄輸入url到顯示頁面的步驟https://github.com/webVueBlog/interview-answe/issues/27

本篇文章的最後,留給你一個面試題,就是上面說到的:“從輸入URL到頁面展示,這中間發送了什麼?”這個問題,如果面試你,你又如何回答呢?

如果你作為面試官,又該考哪些點呢?

閱讀資料

浏覽器工作原理與實踐

https://time.geekbang.org/column/intro/100033601

總結

以上就是今天要講的内容,本文簡單介紹了Chrome流程,梳理了TCP與HTTP協定,了解三次握手,四次揮手流程,感謝閱讀,如果你覺得這篇文章對你有幫助的話,也歡迎把它分享給更多的朋友。

—————END—————